Java多线程学习2——互斥


一、前言

在上一节 (http://www.cnblogs.com/lzhen/p/3917966.html) 中,通过实现Runnable接口,可以实现多线程中的资源的共享,解决了一些基本的问题,但是在实际使用过程中,直接使用其中的第四节中的方法却会产生一些不可预知的问题,现在我们对其中的代码稍作修改,如下所示:

 class MyThread implements Runnable
 {

     private int ticket = 5;  //5张票

     public void run()
     {
         for (int i=0; i<=5; i++)
         {
             if (this.ticket > 0)
             {
                 System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);
                     try
                     {
                         Thread.sleep(500);
                     }
                     catch (InterruptedException e)
                     {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                     }

                 }
             }
         }

 }
 public class TestThread {

     public static void main(String [] args)
     {
         MyThread my = new MyThread();
         new Thread(my, "1号窗口").start();
         new Thread(my, "2号窗口").start();
         new Thread(my, "3号窗口").start();
     }
 }

这段代码运行的结果为:

 1号窗口正在卖票5
 3号窗口正在卖票3
 2号窗口正在卖票4
 2号窗口正在卖票2
 1号窗口正在卖票1
 3号窗口正在卖票2

当然这个结果也就有很大的不确定性,出现这样的问题的原因是不同的线程在共享同样的资源的时候,出现了碰撞,有可能线程1改变了共享的数据,还没来得及输出,线程2已经使用了,这样的问题在实际中是不允许的。而互斥就是解决这种临界资源问题的一种最简单的方法。


二、synchronized关键字

synchronized关键字是一个修饰符,可以修饰代码块和方法。它的作用是,对于同一个对象来说,当不同的线程都来调用同一个方法或者代码块的时候,必须等待前一个线程执行完之后,才能够开始执行这个方法或者代码块。,使用synchronized关键字修改上面代码,如下所示:

 import java.awt.Desktop.Action;

 class MyThread implements Runnable
 {

     private int ticket = 5; // 5张票

     public void run()
     {
         for (int i = 1; i <= 5; i++)
         {
             synchronized (this)
             {
                 if (this.ticket > 0)
                 {
                     action(this.ticket);
                     try
                     {
                         Thread.sleep(500);
                     }
                     catch (InterruptedException e)
                     {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                     }
                     this.ticket--;

                 }
             }
         }

     }

     public synchronized void action(int ticket)
     {
         System.out.println(Thread.currentThread().getName() + "正在卖票" + ticket);
     }

 }

 public class TestThread
 {

     public static void main(String[] args)
     {
         MyThread my = new MyThread();
         new Thread(my, "1号窗口").start();
         new Thread(my, "2号窗口").start();
         new Thread(my, "3号窗口").start();
     }
 }

这里为了演示synchronized的用法,在代码中不仅用synchronized修饰方法,还用来修饰了代码块,上述代码的实现效果为:

1号窗口正在卖票5
3号窗口正在卖票4
2号窗口正在卖票3
3号窗口正在卖票2
1号窗口正在卖票1

和预期的效果是一致的。

【Java多线程】互斥的更多相关文章

  1. Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock

    本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...

  2. JAVA 多线程同步与互斥

    1. 为什么需要互斥: ​互斥操作  保证了  多线程操作的  原子性 , java的 互斥 语义 有 synchronized 关键字 提供. 主要方式 有  同步代码块 和  同步方法 两种 2. ...

  3. Java多线程之线程的互斥处理

    Java多线程之线程的互斥处理 一.前言 多线程程序中的各个线程都是自由运行的,所以它们有时就会同时操作同一个实例.这在某些情况下会引发问题.例如,从银行账户取款时,余额确认部分的代码应该是像下面这样 ...

  4. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  5. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  6. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  7. 第一章 Java多线程技能

    1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...

  8. java从基础知识(十)java多线程(下)

    首先介绍可见性.原子性.有序性.重排序这几个概念 原子性:即一个操作或多个操作要么全部执行并且执行的过程不会被任何因素打断,要么都不执行. 可见性:一个线程对共享变量值的修改,能够及时地被其它线程看到 ...

  9. Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例

    概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...

随机推荐

  1. Android百度地图开发03之地图控制 + 定位

    前两篇关于百度地图的blog写的是,一些基本图层的展示 和 覆盖物的添加+地理编码和反地理编码. 接下来,这篇blog主要说一些关于地图控制方面的内容和定位功能. 百度地图提供的关于地图的操作主要有: ...

  2. 第一个Struts2程序

    Struts2.3.16, Tomcat6.0.37,Java8 /web.xml <?xml version="1.0" encoding="UTF-8" ...

  3. ruby脚本,随机生成复杂密码

    简单版本: base_char = (32..126).map{|i|i.chr} - ["'",'"'," ", "`",&qu ...

  4. Linux下安装mysql-5.6.4 的图文教程

    在开始安装前,先说明一下mysql-5.6.4与较低的版本在安装上的区别,从mysql-5.5起,mysql源码安装开始使用cmake了,因此当我们配置安装目录./configure --perfix ...

  5. NandFlash详述【转】

    NandFlash详述 转自:http://wenku.baidu.com/view/04d9330bb52acfc789ebc92f.html?re=view 1. 硬件特性: [Flash的硬件实 ...

  6. linux下c程序调用reboot函数实现直接重启【转】

    转自:http://www.blog.chinaunix.net/uid-20564848-id-73878.html linux下c程序调用reboot函数实现直接重启 当然你也可以直接调用syst ...

  7. MySQL 字段常用操作 添加,修改,删除,调整字段顺序

    整理备忘: 添加字段:alter table 表名Add column 字段名 字段类型  默认值 AFTER 字段名 (在哪个字段后面添加) 例子: alter table appstore_sou ...

  8. 选择——ERP信息系统选型

    做一次选择并不难,难的是做一次坚定而正确的选择.TCL电脑公司的ERP软件选型就是一次正确而艰难的选择过程.让我们从头说起吧!­ 业界都知道TCL电脑是IT行业的新入行者,更知道TCL的另一个诠释:& ...

  9. Linux常用到的指令汇总

    Linux常用到的指令汇总 根据鸟哥linux私房菜上定义的:一定要先學會的指令:ls, more, cd, pwd, rpm, ifconfig, find 登入與登出(開機與關機):telnet, ...

  10. java 的UUID的具体用法

    参照JDK public final class UUIDextends Objectimplements Serializable, Comparable<UUID> 表示通用唯一标识符 ...