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 }
这里,先在类里面定义一个锁对象,然后在进入任务之后拿锁锁上,任务结束,开锁,别的线程拿到锁才能进入任务操作。
(我不怕千万人阻挡,只怕自己投降!)