多线程之间的同步控制

问题:

同时运行的几个线程需要共享一个数据,并且要考虑到彼此的状态和动作。

例如,当一个线程对共享的数据进行操作时,在没有完成相关操作之前,不允许其他线程打断它,否则会破坏数据的完整性。也就是说,被多个线程共享的数据在同一时刻只允许一个线程处于操作之中。

实现原理:

为了保证线程安全,使用“锁旗标”;

当线程A获得了一个对象的锁旗标后,线程B若也想获得该对象的锁旗标,就必须等待线程A完成规定的操作并释放出锁旗标后,才能获得该对象的锁旗标,并执行线程B中的操作。

代码实现:

public class ProducerAndConsumer {

	/**
	 * 假定开始售票处并没有票,一个线程往里存票,另一个线程则往外卖票。
	 * 新建一个票类对象,让存票和售票线程都访问它。
	 * 两个线程共享同一个数据对象来实现对同一份数据的操作
	 */
	public static void main(String[] args) {
		Tickets t=new Tickets(10); //新建一个票类对象,总票数作为参数
		new Producer(t).start(); //以票类对象为参数创建存票线程对象,并启动
		new Consumer(t).start();//以同一个票类对象为参数创建售票线程,并启动

	}

}

//票类
class Tickets{
	int number=0; //票号
	int size;	//总票数
	boolean available=false; //表示目前是否有票可售
	public Tickets(int size){this.size=size;}//构造函数,传入总票数参数
}

//存票线程
class Producer extends Thread{
	Tickets t=null;
	public Producer(Tickets t){this.t=t;}//构造函数:以一个票类为参数
	@Override
	public void run() {
		while(t.number<t.size){//限制循环条件为存票序号小于总票数
			synchronized(t){//申请对象t的锁旗标
				System.out.println("Producer puts ticket "+(++t.number));
				t.available=true;//可以买票
			}//自动释放锁旗标

		}
	}
}

//售票线程
class Consumer extends Thread{
	Tickets t=null;
	int i=0;
	public Consumer(Tickets t){//构造函数:以一个票类对象为参数
		this.t=t;
	}
	public void run(){

		synchronized(t){
			while(i<t.size){ //循环条件为售票序号小于总票数
				if(t.available==true && i<=t.number){ //有票可售且小于目前票序号
					System.out.println("consumer buys ticket "+(++i));
				}
				if(i==t.number){//当票已售到当前序号,则不可售
					t.available=false;
				}
			}
		}

	}
}

一个对象的锁旗标只有一个,所以利用对一个对象锁旗标的争夺,可以实现不同线程的互斥效果。当一个线程获得锁旗标后,需要改锁旗标的其他线程只能处于等待状态。

另外, 也可以将此关键字加在方法上:

//取票方法
	public synchronized void sell(){
		if(!available){ //如果没有存票,则售票线程等待
			try{
				wait();
			}
			catch(Exception e){

			}
			System.out.println("consumer buys ticket "+(number));
			available=false;
			notify();//售票唤醒存票线程开始存票
			if(number==size){
				number=size+1;//在售完最后一张票后,设置一个结束标志
			}//number>size表示售票结束
		}
	}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 01:42:22

多线程之间的同步控制的相关文章

多线程之间的通信实例讲解

                 多线程之间的通信实例讲解对于线程来说,说白了,就是一个函数,如果大家对于这章函数都有理解,那我对于操作系统,线程和进程间的通信会有一个新的认识!接下来我会对每一行代码进行注释,在此过程中,大家也可以对c语言有一个崭新的认识. 第一个函数,创建两个线程. #include <stdio.h>#include <pthread.h>    这个头函数要包含,因为我们后续用的函数都是系统调用,因此需要申请头函数   这样在编译的时候,就可以找到此函数的源

多线程之间的通信(等待唤醒机制、Lock 及其它线程的方法)

一.多线程之间的通信. 就是多个线程在操作同一份数据, 但是操作的方法不同. 如: 对于同一个存储块,其中有两个存储位:name   sex, 现有两个线程,一个向其中存放数据,一个打印其中的数据. 为了解决上述问题中的安全问题(在存放线程进行存放操作的时候, 打印线程不能对共有数据进行操作),所以应当对两个线程       操作共有数据的代码部分进行同步(使用synchronized(),来进行同步, 注意 :使用同一个对象作为同步锁. 二.等待唤醒机制. 在上述案例实现过后运行,会发现:打印

Android多线程研究(6)——多线程之间数据隔离

在上一篇<Android多线程研究(5)--线程之间共享数据>中对线程之间的数据共享进行了学习和研究,这一篇我们来看看如何解决多个线程之间的数据隔离问题,什么是数据隔离呢?比如说我们现在开启了两个线程,这两个线程都要同时给同一个全局变量data赋值,各个线程操作它赋值后的变量数据,这里就需要用到隔离.先看一段代码: import java.util.Random; public class ThreadLocalTest { private static int data = 0; publi

Nhibernate多线程之间Session的问题

? 背景:系统针对业务逻辑层提供了AOP的NHibernate Session,会话对象是通过Spring.net管理的.但在业务逻辑层里面有些方法实行了异步线程池调用数据访问接口,抛出异常提示:No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here. ? 分析原因:当前线程和Spring.net创建Session绑定了,多线程直接切

【java】-- 多线程之间实现通讯

1.多线程之间如何实现通讯 1.1.什么是多线程之间通讯? 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同. 画图演示 1.2.多线程之间通讯需求 需求:第一个线程写入(input)用户,另一个线程取读取(out)用户.实现读一个,写一个操作. 2.代码实现基本实现 2.1.共享资源源实体类 class Res {      public String userSex;      public String userName; } 输入线程资源 class IntThrad

多线程之间实现通讯

多线程之间如何实现通讯 什么是多线程之间通讯?  多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同. 多线程之间通讯需求 需求:第一个线程写入(input)用户,另一个线程取读取(out)用户.实现读一个,写一个操作. 代码实现基本实现 共享资源源实体类 class Res { public String userSex; public String userName; } 输入线程资源 class IntThrad extends Thread { private Res

多线程之间通讯

什么是多线程之间通信? 多个线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的的动作不同. 如,一个线程对资源进行写的操作,一个线程对资源进行读的操作. 例子: 共享资源类: class Res { public String userSex; public String userName; } 写操作类 class IntThrad extends Thread { private Res res; public IntThrad(Res res) { this.res = res;

java多线程之间的通信

如何让两个线程依次执行?那如何让 两个线程按照指定方式有序交叉运行呢?四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的三个运动员各自准备,等到三个人都准备好后,再一起跑子线程完成某件任务后,把得到的结果回传给主线程1.如何让两个线程依次执行?#Copypublic static void main(String[] args) {demo1();/结果: t1>>pirnt:1t2>>pirnt:1t2>>pir

【Linux】多进程与多线程之间的区别

http://blog.csdn.net/byrsongqq/article/details/6339240 网络编程中设计并发服务器,使用多进程与多线程 ,请问有什么区别?  答案一: 1,进程:子进程是父进程的复制品.子进程获得父进程数据空间.堆和栈的复制品. 2,线程:相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列. 两者都可以提高程序的并发度,提高程序运行效率和响应时间. 线程和进程在使用上各有优缺点:线程执行开