java 多线程学习笔记之 线程互斥分析

虾米哥 阅读:270 2021-03-31 22:41:14 评论:0

许多线程共享同一数据,这种情况在现实的生活中也是经常发生的,比如火车站的火车票售票系统。火车票售票系统是一个常年运行的系统,为了满足乘客的需求,我们不能只设一个窗口,必须设很多的售票窗口,每个售票窗口就像一个线程,它们各自运行,共同访问相同的数据——火车票的数量,下面我们用多线程模仿一下火车票售票系统:

相关测试代码:

package com.example.ticker; 
 
public class Ticker { 
	// 初始化火车票数量 
	private int tickers = 0; 
 
	public int getTickers() { 
		return tickers; 
	} 
 
	public void setTickers(int tickers) { 
		this.tickers = tickers; 
	} 
 
	// 初始化构造函数 
	public Ticker(int tickers) { 
		super(); 
		this.tickers = tickers; 
	} 
 
	// 售票方法 
	public void sell() { 
 
		if (tickers > 0) { 
			System.out.println("sell tickets:" + tickers); 
			tickers--; 
		} 
 
	} 
 
} 
package com.examplex.threadstate; 
 
import com.example.ticker.Ticker; 
 
public class TicketRunnable implements Runnable { 
	private Ticker ticker; 
	private String name; 
 
	public Ticker getTicker() { 
		return ticker; 
	} 
 
	public void setTicker(Ticker ticker) { 
		this.ticker = ticker; 
	} 
 
	public String getName() { 
		return name; 
	} 
 
	public void setName(String name) { 
		this.name = name; 
	} 
 
	public TicketRunnable(String name, Ticker ticker) { 
		super(); 
		this.ticker = ticker; 
		this.name = name; 
	} 
 
	@Override 
	public void run() { 
		// 死循环 
		while (true) { 
			// 条件判断 
			if (ticker.getTickers() > 0) { 
				System.out.println("当前线程为:" + this.name); 
				ticker.sell(); 
			} 
 
		} 
 
	} 
 
} 
package com.example.main; 
 
import com.example.ticker.Ticker; 
import com.examplex.threadstate.MyRunnable; 
import com.examplex.threadstate.MyThread; 
import com.examplex.threadstate.TicketRunnable; 
 
public class TestMain { 
 
	/** 
	 * @param args 
	 */ 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		Ticker ticker = new Ticker(100); 
 
		Thread thread1 = new Thread(new TicketRunnable("线程一", ticker)); 
		Thread thread2 = new Thread(new TicketRunnable("线程二", ticker)); 
		Thread thread3 = new Thread(new TicketRunnable("线程三", ticker)); 
		Thread thread4 = new Thread(new TicketRunnable("线程四", ticker)); 
 
		thread1.start(); 
		thread2.start(); 
		thread3.start(); 
		thread4.start(); 
 
	} 
 
}

相关测试结果:

当前线程为:线程一 
sell tickets:100 
当前线程为:线程一 
当前线程为:线程三 
sell tickets:99 
当前线程为:线程一 
sell tickets:98 
当前线程为:线程一 
sell tickets:97 
当前线程为:线程一 
sell tickets:96 
当前线程为:线程一 
sell tickets:95 
当前线程为:线程一 
sell tickets:94 
当前线程为:线程一 
sell tickets:93 
当前线程为:线程一 
sell tickets:92 
当前线程为:线程一 
sell tickets:91 
当前线程为:线程一 
sell tickets:90 
当前线程为:线程一 
sell tickets:89 
当前线程为:线程一 
sell tickets:88 
当前线程为:线程一 
sell tickets:87 
当前线程为:线程一 
sell tickets:86 
当前线程为:线程一 
sell tickets:85 
当前线程为:线程一 
sell tickets:84 
当前线程为:线程一 
sell tickets:83 
当前线程为:线程一 
sell tickets:82 
当前线程为:线程一 
sell tickets:81 
当前线程为:线程一 
sell tickets:80 
当前线程为:线程一 
sell tickets:79 
当前线程为:线程一 
sell tickets:78 
当前线程为:线程一 
sell tickets:77 
当前线程为:线程一 
sell tickets:76 
当前线程为:线程一 
sell tickets:75 
当前线程为:线程一 
sell tickets:74 
当前线程为:线程一 
sell tickets:73 
当前线程为:线程一 
sell tickets:72 
当前线程为:线程一 
sell tickets:71 
当前线程为:线程一 
sell tickets:70 
当前线程为:线程一 
sell tickets:69 
当前线程为:线程一 
sell tickets:68 
当前线程为:线程一 
sell tickets:67 
当前线程为:线程一 
sell tickets:66 
当前线程为:线程一 
sell tickets:65 
当前线程为:线程一 
sell tickets:64 
当前线程为:线程一 
sell tickets:63 
当前线程为:线程一 
sell tickets:62 
当前线程为:线程一 
sell tickets:61 
当前线程为:线程一 
sell tickets:60 
当前线程为:线程一 
sell tickets:59 
当前线程为:线程一 
sell tickets:58 
当前线程为:线程一 
sell tickets:57 
当前线程为:线程一 
sell tickets:56 
当前线程为:线程一 
sell tickets:55 
当前线程为:线程一 
sell tickets:54 
当前线程为:线程一 
sell tickets:53 
当前线程为:线程一 
sell tickets:52 
当前线程为:线程一 
sell tickets:51 
当前线程为:线程一 
sell tickets:50 
当前线程为:线程一 
sell tickets:49 
当前线程为:线程一 
sell tickets:48 
当前线程为:线程一 
sell tickets:47 
当前线程为:线程一 
当前线程为:线程四 
sell tickets:46 
当前线程为:线程一 
sell tickets:45 
当前线程为:线程一 
sell tickets:44 
当前线程为:线程一 
当前线程为:线程二 
sell tickets:43 
当前线程为:线程二 
sell tickets:42 
当前线程为:线程二 
sell tickets:41 
当前线程为:线程二 
sell tickets:40 
当前线程为:线程二 
sell tickets:39 
当前线程为:线程二 
sell tickets:38 
当前线程为:线程二 
sell tickets:37 
当前线程为:线程二 
sell tickets:36 
当前线程为:线程二 
sell tickets:35 
当前线程为:线程二 
sell tickets:34 
当前线程为:线程二 
sell tickets:33 
当前线程为:线程二 
sell tickets:32 
当前线程为:线程二 
sell tickets:31 
当前线程为:线程二 
sell tickets:30 
当前线程为:线程二 
sell tickets:29 
当前线程为:线程二 
sell tickets:28 
当前线程为:线程二 
sell tickets:27 
当前线程为:线程二 
sell tickets:26 
当前线程为:线程二 
sell tickets:25 
当前线程为:线程二 
sell tickets:24 
当前线程为:线程二 
sell tickets:23 
当前线程为:线程二 
sell tickets:22 
当前线程为:线程二 
sell tickets:21 
当前线程为:线程二 
sell tickets:20 
sell tickets:99 
当前线程为:线程三 
sell tickets:18 
当前线程为:线程三 
sell tickets:17 
当前线程为:线程三 
sell tickets:16 
当前线程为:线程三 
sell tickets:15 
当前线程为:线程三 
sell tickets:14 
当前线程为:线程三 
sell tickets:13 
当前线程为:线程三 
sell tickets:12 
当前线程为:线程三 
sell tickets:11 
当前线程为:线程三 
sell tickets:10 
当前线程为:线程三 
sell tickets:9 
当前线程为:线程三 
sell tickets:8 
当前线程为:线程三 
sell tickets:7 
当前线程为:线程三 
sell tickets:6 
当前线程为:线程三 
sell tickets:5 
当前线程为:线程三 
sell tickets:4 
当前线程为:线程三 
sell tickets:3 
当前线程为:线程三 
sell tickets:2 
当前线程为:线程三 
sell tickets:1 
当前线程为:线程二 
sell tickets:43 
sell tickets:43 

程序输出了线程0、1、2、4四个线程从第100张票卖到第1张票的过程,存在火车票多次重复出售的问题,这是在实际火车票出售中,是绝对不允许出现这样的问题。遇到了不对的情况,我们就应该得想办法解决它,在Java中运用互斥的方法解决这个问题。

什么叫互斥?

多线程同时共享同一数据(内存区域),每个线程都尝试操作该数据,从而导致数据被破坏,这种现象称为争用条件(互斥)。

java 如何解决互斥问题?

互斥操作的控制,Java提供了关键字synchronized进行的。synchronized可以修饰方法,也可以修饰代码段。其代表的含义就是:进入他修饰的这段代码内的线程必须先去获取一个特定对象的锁定标示,并且虚拟机保证这个标示一次只能被一条线程拥有。


进过上面的描述,来进行修改我们的Ticker类

package com.example.ticker; 
 
public class Ticker { 
	//初始化火车票数量 
	private int tickers=0; 
	 
	private Object lock=new Object(); 
 
	public int getTickers() { 
		return tickers; 
	} 
 
	public void setTickers(int tickers) { 
		this.tickers = tickers; 
	} 
	//初始化构造函数 
	public Ticker(int tickers) { 
		super(); 
		this.tickers = tickers; 
	} 
	 
	//售票方法 
	public void sell(){ 
		synchronized(lock){ 
			if(tickers>0){ 
				System.out.println("sell tickets:"+tickers); 
				tickers--; 
			} 
		} 
		 
	} 
	 
	 
	 
 
} 
演示结果:
当前线程为:线程一 
sell tickets:100 
当前线程为:线程一 
sell tickets:99 
当前线程为:线程二 
sell tickets:98 
当前线程为:线程二 
sell tickets:97 
当前线程为:线程二 
sell tickets:96 
当前线程为:线程二 
sell tickets:95 
当前线程为:线程二 
sell tickets:94 
当前线程为:线程二 
sell tickets:93 
当前线程为:线程二 
sell tickets:92 
当前线程为:线程二 
sell tickets:91 
当前线程为:线程二 
sell tickets:90 
当前线程为:线程二 
sell tickets:89 
当前线程为:线程二 
sell tickets:88 
当前线程为:线程二 
sell tickets:87 
当前线程为:线程二 
sell tickets:86 
当前线程为:线程二 
sell tickets:85 
当前线程为:线程二 
sell tickets:84 
当前线程为:线程二 
sell tickets:83 
当前线程为:线程二 
sell tickets:82 
当前线程为:线程二 
sell tickets:81 
当前线程为:线程二 
sell tickets:80 
当前线程为:线程二 
sell tickets:79 
当前线程为:线程二 
sell tickets:78 
当前线程为:线程二 
sell tickets:77 
当前线程为:线程二 
当前线程为:线程一 
sell tickets:76 
当前线程为:线程二 
sell tickets:75 
当前线程为:线程一 
sell tickets:74 
当前线程为:线程二 
sell tickets:73 
当前线程为:线程一 
sell tickets:72 
当前线程为:线程二 
sell tickets:71 
当前线程为:线程一 
sell tickets:70 
当前线程为:线程二 
sell tickets:69 
当前线程为:线程一 
当前线程为:线程四 
当前线程为:线程三 
sell tickets:68 
当前线程为:线程二 
sell tickets:67 
当前线程为:线程二 
sell tickets:66 
当前线程为:线程二 
sell tickets:65 
当前线程为:线程二 
sell tickets:64 
当前线程为:线程二 
sell tickets:63 
当前线程为:线程二 
sell tickets:62 
当前线程为:线程二 
sell tickets:61 
当前线程为:线程二 
sell tickets:60 
当前线程为:线程二 
sell tickets:59 
当前线程为:线程二 
sell tickets:58 
当前线程为:线程二 
sell tickets:57 
当前线程为:线程二 
sell tickets:56 
当前线程为:线程三 
sell tickets:55 
当前线程为:线程四 
sell tickets:54 
当前线程为:线程一 
sell tickets:53 
当前线程为:线程四 
sell tickets:52 
当前线程为:线程三 
sell tickets:51 
当前线程为:线程二 
sell tickets:50 
当前线程为:线程三 
sell tickets:49 
当前线程为:线程四 
sell tickets:48 
当前线程为:线程一 
sell tickets:47 
当前线程为:线程四 
sell tickets:46 
当前线程为:线程三 
sell tickets:45 
当前线程为:线程三 
sell tickets:44 
当前线程为:线程三 
sell tickets:43 
当前线程为:线程三 
sell tickets:42 
当前线程为:线程三 
sell tickets:41 
当前线程为:线程三 
sell tickets:40 
当前线程为:线程三 
sell tickets:39 
当前线程为:线程三 
sell tickets:38 
当前线程为:线程三 
sell tickets:37 
sell tickets:36 
当前线程为:线程二 
sell tickets:35 
当前线程为:线程二 
sell tickets:34 
当前线程为:线程二 
sell tickets:33 
当前线程为:线程二 
sell tickets:32 
当前线程为:线程二 
sell tickets:31 
当前线程为:线程二 
sell tickets:30 
当前线程为:线程二 
sell tickets:29 
当前线程为:线程二 
sell tickets:28 
当前线程为:线程二 
sell tickets:27 
当前线程为:线程二 
sell tickets:26 
当前线程为:线程二 
sell tickets:25 
当前线程为:线程二 
sell tickets:24 
当前线程为:线程二 
sell tickets:23 
当前线程为:线程二 
sell tickets:22 
当前线程为:线程二 
sell tickets:21 
当前线程为:线程二 
sell tickets:20 
当前线程为:线程二 
sell tickets:19 
当前线程为:线程二 
sell tickets:18 
当前线程为:线程二 
sell tickets:17 
当前线程为:线程二 
sell tickets:16 
当前线程为:线程二 
sell tickets:15 
当前线程为:线程二 
sell tickets:14 
当前线程为:线程二 
sell tickets:13 
当前线程为:线程二 
当前线程为:线程三 
sell tickets:12 
当前线程为:线程四 
sell tickets:11 
当前线程为:线程一 
sell tickets:10 
当前线程为:线程四 
sell tickets:9 
当前线程为:线程三 
sell tickets:8 
当前线程为:线程二 
sell tickets:7 
当前线程为:线程三 
sell tickets:6 
当前线程为:线程四 
sell tickets:5 
当前线程为:线程一 
sell tickets:4 
当前线程为:线程四 
sell tickets:3 
当前线程为:线程三 
sell tickets:2 
当前线程为:线程二 
sell tickets:1 

以上结果才算是正确的。

今天已经完成java 多线程学习之(互斥),下一讲,准备说(java 多线程之同步)


声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

发表评论
搜索
KIKK导航

KIKK导航

排行榜
关注我们

一个IT知识分享的公众号