当前位置: 首页 > news >正文

线程同步机制

并发:多个线程同时操作同一个对象
线程同步的形成条件:队列+

队列

处理多线程问题时,多个线程访问同一个对象,并且某些线程还想修改这个对象.这时候我们就需要线程同步.线程同步其实就是一种等待机制,多个需要同时访问比对象的线程进入这个对象的等待池形成队列,等待前面线程使用完毕,下一个线程再使用。

由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突问题,为了保证数据在方法中被访问时的正确性,在访问时加入锁机制synchronized,当一个线程获得对象的排它锁,独占资源,其他线程必须等待,使用后释放锁即可·存在以下问题:

  • 一个线程持有锁会导致其他所有需要此锁的线程挂起;
  • 在多线程竞争下,加锁,释放锁会导致比较多的上下文切换和调度延时,引起性能问题;
  • 如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能问题.

三大不安全案例

// 不安全的买票
public class UnsafeBuyTicket {public static void main(String[] args) {BuyTicket station = new BuyTicket();Thread t1 = new Thread(station, "张三");Thread t2 = new Thread(station, "李四");Thread t3 = new Thread(station, "王五");t1.start();t2.start();t3.start();}
}class BuyTicket implements Runnable {private int ticket = 10;private boolean flag = true;// 买票public void buy() {if (ticket <= 0) {flag = false;return;}System.out.println(Thread.currentThread().getName()+"获得"+ticket--);}@Overridepublic void run() {while (flag) {buy();}}
}

PixPin_2025-11-03_09-11-44

在三人同时去车站买票这个例子中,可能出现两个人买到同一张票,或者一个人买到负数的票(两个人同时对ticket操作)
```java
public class UnsafeDrawing {public static void main(String[] args) {Account account = new Account("基金", 100);Drawing you = new Drawing(account, 50, "you");Drawing girl = new Drawing(account, 100, "girl");you.start();girl.start();}
}class Account {String name;int balance;public Account(String name, int balance) {this.name = name;this.balance = balance;}
}class Drawing extends Thread{Account account;int drawingMoney;int nowMoney = 0;public Drawing(Account account, int drawingMoney, String name) {super(name);this.account = account;this.drawingMoney = drawingMoney;}@Overridepublic void run() {if (account.balance < drawingMoney) {System.out.println(super.getName() + "余额不足");return;}try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}account.balance -= drawingMoney;nowMoney += drawingMoney;System.out.println(this.getName()+"取钱"+nowMoney);System.out.println(account.name+"余额为"+account.balance);}
}

PixPin_2025-11-03_08-33-52
这里同样是多个线程对同一用户对操作导致的线程不安全问题,中间我们加入了sleep来模拟网络延迟

public class UnsafeList {public static void main(String[] args) {List<String> list = new ArrayList<String>();for (int i = 0; i < 10000; i++) {new Thread(() -> {list.add(Thread.currentThread().getName());}).start();}System.out.println(list.size());}
}

在Java的标准库里,ArrayList是线程不安全的,Vector是线程安全的,可以在这个例子中看出
PixPin_2025-11-03_08-52-37

同步方法

一个实现线程同步的方法是加上synchornized修饰符,包含两种方法,synchornized方法与synchornized块;
这种实现方法的弊端就是不停地加锁释放锁非常浪费资源,所以只在需要进行写操作的时候加锁就好

注意:synchornized默认锁的是this,所以我们在第二个案例中,如果对run加锁锁住了Drawing对象,但是我们操作的account仍然被同时访问,导致存款为负数
我们可以使用同步块来制定锁住对象,如下

public void run() {synchronized (account) {if (account.balance < drawingMoney) {System.out.println(super.getName() + "余额不足");return;}try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}account.balance -= drawingMoney;nowMoney += drawingMoney;}System.out.println(this.getName()+"取钱"+nowMoney);System.out.println(account.name+"余额为"+account.balance);}

第三个案例同样如此

public class UnsafeList {public static void main(String[] args) {List<String> list = new ArrayList<String>();for (int i = 0; i < 10000; i++) {new Thread(() -> {synchronized (list) {list.add(Thread.currentThread().getName());}}).start();}System.out.println(list.size());}
}

CopyOnWriteArrayList

juc提供的一个安全的集合

import java.util.concurrent.CopyOnWriteArrayList;public class TestJUC {public static void main(String[] args) {CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();for (int i = 0; i < 10000; i++) {new Thread(()->{list.add(Thread.currentThread().getName());}).start();}System.out.println(list.size());}
}
http://www.jsqmd.com/news/29897/

相关文章:

  • 2025 年最新电缸源头厂家推荐排行榜:聚焦优质供应企业,助力企业精准选择传动元件合作伙伴同步带电缸/电动缸公司推荐
  • 从客户流失到口碑爆棚:我们如何用ttkefu让满意度飙升30%
  • 这是一场豪赌
  • 2025.11.03
  • MIT_65840测试网络环境的搭建与实现
  • 特征提取之自动编码器
  • 2025 年最新推荐!天津网站建设公司综合实力排行榜:含外贸、高端、模板建站等领域,助力企业选靠谱服务商
  • 2025年新疆高三复读班权威推荐榜单:高三集训班/高三冲刺班/高三复读全日制学校精选
  • 2025 年最新磁健大健康烯磁 60 床垫厂家推荐榜:精选优质品牌,展现卓越品质与专业实力磁健/巴马地磁/地磁 60 床垫公司推荐
  • 服务器文件夹自动同步解决方案,实现高效、安全的数据管理
  • WTAPI框架微信开发经验
  • 高斯分布
  • NSSCTF-Pwn-[HGAME 2023 week1]simple_shellcode
  • 【一句日历】2025年11月
  • Just Daydreaming CSP2025 游记
  • CSP 2025 邮寄
  • .NET 8.0 + Vue 企业级在线培训系统(开源、免费、支持多种主流数据库)
  • 2025年度电厂钢格栅生产厂家TOP5权威推荐:全面解析,精准选型指南
  • 如何排查“链接 HTTPS”问题,工程化思路与iOS抓包流程
  • 2025年靠谱精密轧机服务厂商推荐,精密轧机源头厂家与靠谱生产商全解析
  • 为什么2025的小程序开始“去轻量化”?谈新一代小程序设计趋势
  • 2025年新疆初三复读班权威推荐榜单:中考复读/户籍地中考复读/初三补习班学校精选
  • 2025年中国高效油雾净化设备公司排名:油雾净化设备供应企业与服务商家权威测评与推荐
  • 2025年度边坡防护网正规企业排名:中国五大老牌边坡防护网厂家深度测评
  • vxe-table 如何自定义排序图标按钮,自定义排序
  • MATLAB实现低秩矩阵填充
  • 基于模糊控制理论的锅炉水位控制系统设计与仿真
  • CSPS AK大佬游记拜读
  • 喵喵喵 I
  • 2025年真空泵维修可靠公司排名:真空泵维修哪家可靠