多线程同步
一、同步代码块
lock是一个锁对象,它是同步代码块的的关键
class myThread2 implements Runnable{ private int tickets =10; private final Object lock = new Object();//任意对象类型 @Override public void run() { while(true){ synchronized(lock){ if(tickets >0){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在售出"+tickets--+"张票"); } } } } } public class synchronizeddemo { public static void main(String[] args) { myThread2 run = new myThread2(); Thread t1 = new Thread(run,"t1线程"); Thread t2 = new Thread(run,"t2线程"); Thread t3 = new Thread(run,"t3线程"); t1.start(); t2.start(); t3.start(); }
注意:锁对象不能放到run方法中,否则每个线程运行到run方法是都会创建一个新对象,每个线程都会有一个不同的锁,便不会产生同步效果
二、同步方法
被synchronized修饰的方法在某一时刻只允许一个线程访问,其他线程会发生阻塞,只有当前线程访问结束,其他线程才有机会访问
private int tickets = 10; private final Object lock = new Object();//任意对象类型 @Override public void run() { while(true) { saleTicket(); } } private synchronized void saleTicket(){ synchronized(lock){ if(tickets >0){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在售出"+tickets--+"张票"); } } }
同步方法也有锁,它的锁就是当前调用该方法的对象,也就是this指向的对象。
静态方法也有锁,它的锁是该方法所在类的class对象,可以使用类名.class获取
同步代码锁有好处也有弊端,同步锁解决了多个线程同时访问共享数据时的线程安全问题,加上锁在同一时间只能有一条线程执行,但线程在执行时每次都需要判断锁的状态,每次消耗资源,效率较低
三、同步锁
从JDK5开始JAVA增加了功能强大的Lock锁Lock锁于synchronized隐式锁功能相同,优势在于Lock锁可以让某个线程在持续获取同步锁失败后返回
private final Lock lock = new ReentrantLock();//ReentrantLock是Lock的实现类,也是常用的同步锁 @Override public void run() { while(true) { lock.lock();//加锁 if(tickets >0){ try { Thread.sleep(100); System.out.println(Thread.currentThread().getName()+"正在售出"+tickets--+"张票"); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock();//解锁 } } } }
四、死锁问题
两个线程在运行时都在等待对方的锁,这便造成死锁
class DeadLock implements Runnable{ private boolean flag; //定义两个锁 static Object lock1 = new Object(); static Object lock2 = new Object(); DeadLock(boolean flag){ this.flag =flag; } @Override public void run() { //判断线程的入口 if(flag){ while(true){ synchronized(lock1){ System.out.println(Thread.currentThread().getName()+"is runing"); synchronized (lock2){ System.out.println(Thread.currentThread().getName()+"is running"); } } } }else{ while(true){ synchronized(lock2){ System.out.println(Thread.currentThread().getName()+"is runing"); synchronized (lock1){ System.out.println(Thread.currentThread().getName()+"is running"); } } } } } } public class deadlock { public static void main(String[] args) { //创建Deadlock对象 DeadLock t1 = new DeadLock(true); DeadLock t2 = new DeadLock(false); new Thread(t1,"Thread-1").start(); new Thread(t2,"Thread-2").start(); } }
在上述代码中,两个线程都需要对方的锁,单都无法释放当前的锁,导致程序处于挂起状态
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构