Java多线程学习2——互斥
一、前言
在上一节 (http://www.cnblogs.com/lzhen/p/3917966.html) 中,通过实现Runnable接口,可以实现多线程中的资源的共享,解决了一些基本的问题,但是在实际使用过程中,直接使用其中的第四节中的方法却会产生一些不可预知的问题,现在我们对其中的代码稍作修改,如下所示:
1 class MyThread implements Runnable 2 { 3 4 private int ticket = 5; //5张票 5 6 public void run() 7 { 8 for (int i=0; i<=5; i++) 9 { 10 if (this.ticket > 0) 11 { 12 System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--); 13 try 14 { 15 Thread.sleep(500); 16 } 17 catch (InterruptedException e) 18 { 19 // TODO Auto-generated catch block 20 e.printStackTrace(); 21 } 22 23 } 24 } 25 } 26 27 } 28 public class TestThread { 29 30 public static void main(String [] args) 31 { 32 MyThread my = new MyThread(); 33 new Thread(my, "1号窗口").start(); 34 new Thread(my, "2号窗口").start(); 35 new Thread(my, "3号窗口").start(); 36 } 37 }
这段代码运行的结果为:
1 1号窗口正在卖票5 2 3号窗口正在卖票3 3 2号窗口正在卖票4 4 2号窗口正在卖票2 5 1号窗口正在卖票1 6 3号窗口正在卖票2
当然这个结果也就有很大的不确定性,出现这样的问题的原因是不同的线程在共享同样的资源的时候,出现了碰撞,有可能线程1改变了共享的数据,还没来得及输出,线程2已经使用了,这样的问题在实际中是不允许的。而互斥就是解决这种临界资源问题的一种最简单的方法。
二、synchronized关键字
synchronized关键字是一个修饰符,可以修饰代码块和方法。它的作用是,对于同一个对象来说,当不同的线程都来调用同一个方法或者代码块的时候,必须等待前一个线程执行完之后,才能够开始执行这个方法或者代码块。,使用synchronized关键字修改上面代码,如下所示:
1 import java.awt.Desktop.Action; 2 3 4 class MyThread implements Runnable 5 { 6 7 private int ticket = 5; // 5张票 8 9 10 public void run() 11 { 12 for (int i = 1; i <= 5; i++) 13 { 14 synchronized (this) 15 { 16 if (this.ticket > 0) 17 { 18 action(this.ticket); 19 try 20 { 21 Thread.sleep(500); 22 } 23 catch (InterruptedException e) 24 { 25 // TODO Auto-generated catch block 26 e.printStackTrace(); 27 } 28 this.ticket--; 29 30 } 31 } 32 } 33 34 } 35 36 37 public synchronized void action(int ticket) 38 { 39 System.out.println(Thread.currentThread().getName() + "正在卖票" + ticket); 40 } 41 42 } 43 44 45 public class TestThread 46 { 47 48 public static void main(String[] args) 49 { 50 MyThread my = new MyThread(); 51 new Thread(my, "1号窗口").start(); 52 new Thread(my, "2号窗口").start(); 53 new Thread(my, "3号窗口").start(); 54 } 55 }
这里为了演示synchronized的用法,在代码中不仅用synchronized修饰方法,还用来修饰了代码块,上述代码的实现效果为:
1号窗口正在卖票5 3号窗口正在卖票4 2号窗口正在卖票3 3号窗口正在卖票2 1号窗口正在卖票1
和预期的效果是一致的。
时间: 2024-08-30 12:47:57