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. C++:流类库与输入输出

    7.2.1 C++的输入输出流 ios:流基类(抽象类) istream:通用输入流类和其他输入流的基类 ostream:通用输出流类和其他输出类的基类 iostream:通用输入输出流类和其他输入输 ...

  2. Android EditText获取光标位置并插入字符删除字符

    1.获取光标位置 int index = editText.getSelectionStart(); 2.在光标处插入字符 int index = editText.getSelectionStart ...

  3. Jboss调优——最佳线程数

     在设置jboss的参数中,maxThreads(最大线程数)和acceptCount(最大等待线程数)是两个非常重要的指标,直接影响到程序的QPS.本文讲解jboss连接的运行原理,以及如何设置这两 ...

  4. JSP的执行过程及其异常处理机制

    1.JSP的执行过程     虽然JSP感觉上很像一般的HTML网页,但事实上它是以Servlet的形式被运行的.因为JSP文件在第一次运行的时候会先解释成Servlet源文件,然后编译成Servle ...

  5. code manager tools svn服务安装配置

    svn server 安装配置: 下载地址:http://www.visualsvn.com/server/download/ 然后安装图一步一步前进: 1.点击download now: 2.点击N ...

  6. 怎样用delphi关闭并重新启动 explorer.exe进程

    uses Tlhelp32; function KillTask(ExeFileName:string):integer; const PROCESS_TERMINATE = $0001; var C ...

  7. UVA 11019 Matrix Matcher(ac自动机)

    题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  8. Oracle中添加视图

     CREATE or REPLACE view view_will as   select college.collegeid,mat.stuid,sum(score.chinese+score.ma ...

  9. document.body.innerHTML用jquery如何表示

    $("body").html('XXXX');     //这个是赋值 $("body").html();    //这个是获取HTML的内容

  10. LA 3602 DNA Consensus String

    最近审题老是一错再错,Orz 题目中说求一个Hamming值总和最小的字符串,而不是从所给字符中找一个最小的 这样的话,我们逐列处理,所求字符串当前位置的字符应该是该列中出现次数最多其次ASCII值最 ...