zoukankan      html  css  js  c++  java
  • 【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

           和预期的效果是一致的。

  • 相关阅读:
    【BZOJ2959】—长跑(LCT维护双连通分量+并查集)
    【BZOJ5394】【Ynoi2016】—炸脖龙(树状数组+广义欧拉定理)
    【BZOJ2588】【Spoj10628】—Count on a tree(主席树)
    SCOI2019爆零记+总结反思
    【SCOI2019】—DAY1T1平台跳跃(打表+高精度)
    省选模板复习—【字符串】
    省选模板复习—【数据结构】
    【BZOJ3572】【HNOI2014】—世界树(虚树+倍增+dp)
    python paramiko 模块
    python sys模块
  • 原文地址:https://www.cnblogs.com/charles04/p/4326105.html
Copyright © 2011-2022 走看看