【Java多线程】互斥
Java多线程学习2——互斥
一、前言
在上一节 (http://www.cnblogs.com/charles04/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
和预期的效果是一致的。