java线程之线程同步

本篇由于涉及多线程操作,所以线程是使用实现Runnable接口来创建的。

在上篇所示线程任务中,我们不难发现,是存在三步操作的:

第一:打印语句;

第二:计算sum=sum-1;

第三:线程休眠。

那么,在多线程操作中,可能会出现,第一个线程准备打印,还没有进行sum=sum-1计算时,第二个线程也开始打印语句了,

那么此时第二个线程打印语句中的sum值由于还没有经过线程1处理,所以线程二打印的语句也会是“还剩49个苹果”,要解决

这个问题,就引入了线程同步概念,将线程中的所有操作(任务)视为同步处理,是不分先后的。那么,只要线程1比线程2早

开启,哪怕是1纳秒,线程2中num的初始值也是49,所以线程2输出语句是“还剩48个苹果”,线程同步有三种方法。这里只针对

具体任务贴出同步代码操作。

1.同步代码块

 1     public void eat() {
 2         synchronized (this) {
 3             if (sum1 > 0) {
 4                 System.out.println(Thread.currentThread().getName() + "吃了一个苹果," + "还剩" + --sum1 + "个苹果");
 5                 try {
 6                     Thread.sleep(100);
 7                 } catch (InterruptedException e) {
 8                     e.printStackTrace();
 9                 }
10             }
11         }
12     }

这里的this指向一个同步监听对象,可以理解为一个多线程共享资源,也就是Runnable的实例。

2.同步方法

 1  synchronized public void eat() {
 2         if (sum1 > 0) {
 3             System.out.println(Thread.currentThread().getName() + "吃了一个苹果," + "还剩" + --sum1 + "个苹果");
 4             try {
 5                 Thread.sleep(100);
 6             } catch (InterruptedException e) {
 7                 e.printStackTrace();
 8             }
 9         }
10     }

由于run方法不能用synchronized修饰,只能新建一个该修饰符修饰的方法,放到run里面执行。

3.同步锁(Lock)

 1     final Lock lock = new ReentrantLock();
 2 
 3     public void eat() {
 4         lock.lock();   //拿锁关门
 5         if (sum1 > 0) {
 6             System.out.println(Thread.currentThread().getName() + "吃了一个苹果," + "还剩" + --sum1 + "个苹果");
 7             try {
 8                 Thread.sleep(100);
 9             } catch (InterruptedException e) {
10                 e.printStackTrace();
11             } finally {
12                 lock.unlock(); //开锁
13             }
14         }
15     }

这里,先在类里面定义一个锁对象,然后在进入任务之后拿锁锁上,任务结束,开锁,别的线程拿到锁才能进入任务操作。

原文地址:https://www.cnblogs.com/eco-just/p/7770435.html