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. 使用shell查看局域网中主机的IP地址

    此脚本只是快速查看所在局域网中其它主机的IP地址,如果对方设置了禁ping,则无法显示出此主机的IP地址: #!/bin/bash ` do ping -c2 .$i &>/dev/nu ...

  3. spring+mybati java config配置引起的bean相互引用日志报警告问题

    摘要: Error creating bean with name 'XXX': Requested bean is currently in creation: Is there an unreso ...

  4. 运行java -version报cannot restore segment prot after reloc: Permission denied

    linux 安装jdk1.6后,运行java -version,没有出现相关的版本信息,而是出现了以下错误: dl failure on line 685Error: failed /usr/loca ...

  5. windows 7 ssh server for scp

    Software: BvSshServe. (个人用免费,商业收费) scp localfile.txt user_tst@11.111.12.170:'E:\downloads\SSH\auto.p ...

  6. ViewPager的监听事件失效

    主要是因为在我项目使用了PageIndicator,所以这个时候监听事件要写在PageIndicator上. mIndicator.setOnPageChangeListener(new OnPage ...

  7. IE下easyui 缓存问题

    $.ajaxSetup ({   cache: false //关闭AJAX相应的缓存 }); 这一句话就足够了,很管用!

  8. 宏ut_mem_block_t

    /** This struct is placed first in every allocated memory block */ typedef struct ut_mem_block_struc ...

  9. Codeforces 443 B Kolya and Tandem Repeat【暴力】

    题意:给出一个字符串,给出k,可以向该字符串尾部添加k个字符串,求最长的连续重复两次的子串 没有想出来= =不知道最后添加的那k个字符应该怎么处理 后来看了题解,可以先把这k个字符填成'*',再暴力枚 ...

  10. sql的 group by 分组;linq的 group by 分组

    先来看看 linq的,下面的一段linq 是 ,在 学生导入数据的时候,我们根据学生的手机号码和学生名称进行分组,如果有重复的,我们就筛选出来,用到了 linq的 group by,注意这里是new出 ...