线程的同步

一.线程的安全问题:

1.问题:卖票过程中出现重票和错票问题(线程不安全问题)
2.出现原因:当某个线程的操作尚未完成时,其他线程的操作就参与进来。(即多个线程同时共用一块数据)
3.解决措施:当一个线程在操作共享数据时,其他线程不能参与进来(直到原线程操作完其他线程才可以参与进来)
该情况即使在原线程发生了阻塞也不会改变这种情况
4.在Java中通过同步机制来解决线程安全问题

 

二.同步代码块方法:

说明:1.操作共享数据的代码,即为需要被同步的代码(所包的代码不能多也不能少)
2.共享数据:多个线程中共同操作的变量(本例即为ticket)
3.同步监视器(锁):任何一个类的对象都可以作为锁
要求:多个线程必须共同使用同一把锁(否则无法保证线程安全)
补充:可以考虑适用this.class来做锁
好处:较为简易的解决了线程安全问题。
坏处:将多线程转为单线程来解决问题,效率较低


1.同步代码块解决继承Thread类的线程安全问题

代码及解析:

复制代码
 1 class Window extends Thread {
 2     private static int ticket = 100;//所有同类对象共享static变量
 3 
 4     private static Object obj = new Object();//保证用同一把锁
 5 
 6     public void run() {
 7         while (true) {
 8             synchronized (obj) {
 9                 if (ticket > 0) {
10                     try {
11                         Thread.sleep(1000);
12                     } catch (InterruptedException e) {
13                         throw new RuntimeException(e);
14                     }
15                     System.out.println(getName() + "卖票,票号为:" + ticket);
16                     ticket--;
17                 } else {
18                     break;
19                 }
20             }
21         }
22     }
23 }
复制代码

2.解决Runnable接口的实现方式的线程安全问题:

复制代码
 1 class Window2 implements Runnable {
 2     private int ticket = 100;
 3     Object obj = new Object();
 4     @Override
 5     public void run() {
 6         while (true) {
 7             //方式一:同步代码块
 8             synchronized (obj) {
 9                 if (ticket > 0) {
10                     System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
11                     ticket--;
12                 } else {
13                     break;
14                 }
15             }
16         }
17     }
18 }
复制代码

 

三.同步方法

1.同步方法仍然设计到同步监视器(锁),但不需要我们显示声明
2.静态方法的锁为this.class,非静态方法的锁为this

1.使用同步方法解决Thread类的继承问题

复制代码
 1 class Window4 extends Thread {
 2     private static int ticket = 100;//所有同类对象共享static变量
 3 
 4     private static Object obj = new Object();//保证用同一把锁
 5 
 6     public void run() {
 7         while (true) {
 8 
 9         }
10     }
11 
12     private static synchronized void show() {//使用静态同步方法实现(静态保证锁相同(静态使锁设为当前对象的类))
13         if (ticket > 0) {
14             try {
15                 Thread.sleep(100);
16             } catch (InterruptedException e) {
17                 throw new RuntimeException(e);
18             }
19             System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
20             ticket--;
21         }
22     }
23 }
复制代码

 

2.解决Runnable接口的线程安全问题:

复制代码
 1 class Window3 implements Runnable {
 2     private int ticket = 100;
 3     Object obj = new Object();
 4     @Override
 5     public void run() {
 6         while (ticket > 0) {
 7             show();
 8         }
 9     }
10 
11     public synchronized void show() {//使用同步方法
12         if (ticket > 0) {
13             try {
14                 Thread.sleep(1000);
15             } catch (InterruptedException e) {
16                 throw new RuntimeException(e);
17             }
18             System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
19             ticket--;
20         }
21     }
22 }
复制代码

 

四.锁的添加

复制代码
 1 class Window implements Runnable {
 2     private int ticket = 100;
 3     //1.实例化ReentrantLock
 4     private ReentrantLock lock = new ReentrantLock(true);
 5 
 6     public void run() {
 7         try {
 8             //2.调用锁定方法lock()
 9             lock.lock();
10             while (true) {
11                 if (ticket > 0) {
12                     System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
13                     ticket--;
14                 } else {
15                     break;
16                 }
17             }
18         } finally {
19             //3.调用解锁方法unlock()
20             lock.unlock();
21         }
22 
23     }
24 }
复制代码

 

synchronized与Lock的不同点
synchronized机制:在执行完对应的代码块后,自动的释放同步监视器
Lock机制:需要手动的启动同步(Lock()),结束同步也需要手动的实现(Unlock())
posted @   jue1e0  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示