ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
`synchronized`关键字可以实现线程同步机制,防止对共享资源的访问冲突。通常将共享的资源放在同步块或同步方法中。 >[info]使用同步机制控制的代码块一般用**临界区**来描述 [toc] # 1. `synchronized`同步块(不推荐) **1.`synchronized`同步块语法** ``` synchronized(Object) { //... } ``` * 其他线程必须等到`synchronized`这个锁开锁后才能进入里面获取资源 * Object:为任意的对象,每个对象都有**1**和**0**这两个标志位,一个线程A运行到同步块时会首先检查Object对象的标志位,如果发现为**0**状态,则表明同步块正在被其他线程占用,线程A进入就绪状态,直到其它线程释放同步块,这时标志位变为**1**,表明线程A可以进入同步块中享用资源了,这时标志位变为**0**,禁止其他线程进入同步块。 * 同步块的锁定较弱,通常不推荐使用。 **2. 火车站售票案例** 将上节`线程同步机制`中模拟火车站售票系统新增同步机制功能,就可以解决剩余票数不合常理的问题。 ``` public class SynchronizedTest implements Runnable { int num = 10; @Override public void run() { try { while (true) { synchronized ("") { // 同步块, if (num >= 0) { // 假设线程A调用sleep进入了休眠状态,这时线程B可能进入运行状态 // 记住:这只是一种可能,因为线程B可能还没有进入到运行状态,就先被其它线程 // (也可能是线程A)夺取了进入同步块的机会。 Thread.sleep(100); System.out.println("票数剩余:" + num--); } if (num < 0) { System.out.println("对不起,票已售完!"); return; // 退出线程 } } } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { SynchronizedTest t = new SynchronizedTest(); // 四个线程共同访问对象t,共享变量 num Thread tA = new Thread(t); Thread tB = new Thread(t); Thread tC = new Thread(t); Thread tD = new Thread(t); tA.start(); tB.start(); tC.start(); tD.start(); } } ``` 每次运行的结果都如下: ``` 票数剩余:10 票数剩余:9 票数剩余:8 票数剩余:7 票数剩余:6 票数剩余:5 票数剩余:4 票数剩余:3 票数剩余:2 票数剩余:1 票数剩余:0 对不起,票已售完! 对不起,票已售完! 对不起,票已售完! 对不起,票已售完! ``` <br/> # 2. `synchronized`同步方法(推荐) **1. `synchronized`同步方法语法** ``` synchronized void doit() { //.. } ``` 将上面的案例的同步块改成同步方法得出的结果是一样的: ``` public class SynchronizedMethod implements Runnable { int num = 10; @Override public void run() { while (true) { doit(); if (num < 0) { System.out.println("对不起,票已售完!"); return; // 退出线程 } } } // 同步方法,将线程共享的资源放入同步方法中 synchronized void doit() { try { if (num >= 0) { // 假设线程A调用sleep进入了休眠状态,这时线程B可能进入运行状态 // 记住:这只是一种可能,因为线程B可能还没有进入到运行状态,就先被其它线程 // (也可能是线程A)夺取了进入同步块的机会。 Thread.sleep(100); System.out.println("票数剩余:" + num--); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { SynchronizedMethod t = new SynchronizedMethod(); // 四个线程共同访问对象t, 共享变量 num Thread tA = new Thread(t); Thread tB = new Thread(t); Thread tC = new Thread(t); Thread tD = new Thread(t); tA.start(); tB.start(); tC.start(); tD.start(); } } ``` 每次运行的结果都如下: ``` 票数剩余:10 票数剩余:9 票数剩余:8 票数剩余:7 票数剩余:6 票数剩余:5 票数剩余:4 票数剩余:3 票数剩余:2 票数剩余:1 票数剩余:0 对不起,票已售完! 对不起,票已售完! 对不起,票已售完! 对不起,票已售完! ```