【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

       和预期的效果是一致的。

 

posted @ 2015-03-10 15:20  Charles04  阅读(299)  评论(0编辑  收藏  举报