【Java多线程】互斥

Java多线程学习2——互斥


一、前言

在上一节 (http://www.cnblogs.com/lzhen/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

和预期的效果是一致的。

时间: 2024-08-30 12:47:57

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

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

ReentrantLock介绍 ReentrantLock是一个可重入的互斥锁,又被称为"独占锁". 顾名思义,ReentrantLock锁在同一个时间点只能被一个线程锁持有:而可重入的意思是,ReentrantLock锁,可以被单个线程多次获取.ReentrantLock分为"公平锁"和"非公平锁".它们的区别体现在获取锁的机制上是否公平."锁"是为了保护竞争资源,防止多个线程同时操作线程而出错,ReentrantLock在

JAVA多线程同步与互斥

1. 为什么需要互斥: ?    互斥操作  保证了  多线程操作的  原子性 , java的 互斥 语义 有 synchronized 关键字 提供.    主要方式 有  同步代码块 和  同步方法 两种 2. 整数自增操作 常见的线程安全问题: 从内存中 读数据  到寄存器,<---进入一个线程 从寄存器 +1  写会内存 像这种不是一条指令就能完成的操作 ,并且 有多个线程操作统一资源的时候 ,要保证 上面 三步操作一次执行完,而不被其他线程干扰(原子性:要么  都不执行 ,要么 全部执

(转载)Java多线程入门理解

转载出处http://blog.csdn.net/evankaka 写在前面的话:此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢?如果你觉得此文很简单,那推荐你看看Java并发包的的线程池(Java并发编程与技术内幕:线程池深入理解),或者看这个专栏:Java并发编程与技术内幕.你将会对Java里头的高并发场景下的线程有更加深刻的理解. 目录(?)[-] 一扩展javalangThread类 二实现javalan

40个Java多线程问题总结

前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行总结的,因此罗列了40个多线程的问题. 这些多线程的问题,有些来源于各大网站.有些来源于自己的思考.可能有些问题网上有.可能有些问题对应的答案也有.也可能有些各位网友也都看过,但是本文写作的重心就是所有的问题都会按照自己的理解回答一遍,不会去看网上的答案,因此可能有些问题讲的不对,能指正的希望大家不

【转】 Java 多线程之一

转自   Java 多线程 并发编程 一.多线程 1.操作系统有两个容易混淆的概念,进程和线程. 进程:一个计算机程序的运行实例,包含了需要执行的指令:有自己的独立地址空间,包含程序内容和数据:不同进程的地址空间是互相隔离的:进程拥有各种资源和状态信息,包括打开的文件.子进程和信号处理. 线程:表示程序的执行流程,是CPU调度执行的基本单位:线程有自己的程序计数器.寄存器.堆栈和帧.同一进程中的线程共用相同的地址空间,同时共享进进程锁拥有的内存和其他资源. 2.Java标准库提供了进程和线程相关

JAVA多线程面试题

1.Thread 类中的start() 和 run() 方法有什么区别? Thread.start()方法(native)启动线程,使之进入就绪状态,当cpu分配时间该线程时,由JVM调度执行run()方法. 当你调用start()方法时你将创建新的线程,并且执行在run()方法里的代码.但是如果你直接调用run()方法,它不会创建新的线程也不会执行调用线程的代码. 2.Java中Runnable和Callable有什么不同? Runnable和Callable都代表那些要在不同的线程中执行的任

Java多线程学习

写在前面的话:此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢?如果你觉得此文很简单,那推荐你看看Java并发包的的线程池(Java并发编程与技术内幕:线程池深入理解),或者看这个专栏:Java并发编程与技术内幕.你将会对Java里头的高并发场景下的线程有更加深刻的理解. 目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线

Java多线程基础(一)

线程与进程 1 线程:进程中负责程序执行的执行单元线程本身依靠程序进行运行线程是程序中的顺序控制流,只能使用分配给程序的资源和环境 2 进程:执行中的程序一个进程至少包含一个线程 3 单线程:程序中只存在一个线程,实际上主方法就是一个主线程 4 多线程:在一个程序中运行多个任务目的是更好地使用CPU资源 5  在Java语言中,引入对象互斥锁的概念,保证共享数据操作的完整性. 每个对象都对应于一个可称为"互斥锁"的标记,这个标记保证在任一时刻,只能有一个线程访问对象用关键字synchr

Java多线程(五) Lock接口,ReentranctLock,ReentrantReadWriteLock

在JDK5里面,提供了一个Lock接口.该接口通过底层框架的形式为设计更面向对象.可更加细粒度控制线程代码.更灵活控制线程通信提供了基础.实现Lock接口且使用得比较多的是可重入锁(ReentrantLock)以及读写锁(ReentrantReadWriteLock). 1. ReentrantLock 在Java多线程(二) 多线程的锁机制 里面,已经总结过通过使用Synchronized关键字实现线程内的方法锁定.但使用Synchronized关键字有一些局限性,上锁和释放锁是由JVM决定的