多线程之间的同步控制

问题:

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

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

 

实现原理:

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

当线程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-10-25 11:40:03

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

单处理器中,多进程或多线程之间是否需要使用内存屏障

问题描述 单处理器中,多进程或多线程之间是否需要使用内存屏障 在看Linux内核内存屏障时,文章中写道"只有在存在多CPU交互或CPU与设备交互的情况下才可能需要用到内存屏障.",对此表示怀疑,难道单CPU中,两个进程或两个线程间就不需要用了么? 解决方案 使用LOCK和UNLOCK之后, 一般就不再需要其他内存屏障了(但是注意"MMIO写屏障"章节中所提到的例外). 只有在存在多CPU交互或CPU与设备交互的情况下才可能需要用到内存屏障. 如果可以确保某段代码中不

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

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

《 Java并发编程从入门到精通》第5章 多线程之间交互:线程阀

作者:张振华    购买链接:天猫商城 (投入多少,收获多少.参与多深,领悟多深,京东,亚马逊,当当均有销售.)   5.1 线程安全的阻塞队列BlockingQueue (1)先理解一下Queue.Deque.BlockingQueue的概念: Queue(队列) :用于保存一组元素,不过在存取元素的时候必须遵循先进先出原则.队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作.进行插入操作的端称为队尾,进行删除操作的端称为队头.队列中没有

java多线程中两个容器之间的同步

问题描述 java多线程中两个容器之间的同步 写了一个多线程的爬虫(对多线程不熟悉),但是每次队列中都有重复的元素,我把代码逻辑贴上来,大家帮我看一下,谢谢了: 在进程中: queue = LinkedBlockingQueue set = ConcurrentSkipListSet 在每个进程中使用了bfs bfs: while(!queue.empty()){ s = queue.poll() //...逻辑代码 set.add(s) //对s所有子状态扩展 for(son : s.sons

java多线程实现服务器端与多客户端之间的通信_java

用java语言构建一个网络服务器,实现客户端和服务器之间通信,实现客户端拥有独立线程,互不干扰. 应用多线程来实现服务器与多线程之间的通信的基本步骤 服务器端创建ServerSocket,循环调用accept()等待客户端链接 客户端创建一个Socket并请求和服务器端链接 服务器端接受客户端请求,创建socekt与该客户端建立专线链接 建立链接的socket在一个单独的线程上对话 服务器继续等待新的链接 服务器端Server.java package test.concurrent.socke

Java多线程程序设计入门

程序|多线程|设计 在Java语言产生前,传统的程序设计语言的程序同一时刻只能单任务操作,效率非常低,例如程序往往在接收数据输入时发生阻塞,只有等到程序获得数据后才能继续运行. 随着Internet的迅猛发展,这种状况越来越不能让人们忍受:如果网络接收数据阻塞,后台程序就处于等待状态而不继续任何操作,而这种阻塞是经常会碰到的,此时CPU资源被白白的闲置起来.如果在后台程序中能够同时处理多个任务,该多好啊!应Internet技术而生的Java语言解决了这个问题,多线程程序是Java语言的一个很重要

iOS开发多线程篇—多线程简单介绍

一.进程和线程 1.什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ.Xcode,系统就会分别启动2个进程 通过"活动监视器"可以查看Mac系统中所开启的进程 2.什么是线程 1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程) 线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行 比如使用酷狗播放音乐.使用迅雷下载电影,都需要在线程中执行 3.线程的串行 1个线程中任务的执

Java多线程基础总结四:ThreadLocal

说到ThreadLocal,首先说说这个类的命名.直观上看好像是个Thread的什么亲戚,但其实它想表达的意思是线程本地变量,也就是说每 个线程自己的变量.它作为一个JDK5以后支持范型的类,主要是想利用范型把非线程安全的共享变量,封装成绑定线程的安全不共享变量. 这样的解释我想我们多半能猜出它的实现思路:把一个共享变量在每个线程使用时,初始化一个副本,并且和线程绑定.以后所有的线程对 共享变量的操作都是对线程内部那个副本,完全的线程内部变量的操作. 要实现这样功能类的设计,主要技术点是要能把副

Windows 95多线程间同步事件的控制方法

摘要:在Windows 95中所有的应用程序实际上都以是线程的方式运行的.在设计多线程应用程序中有时必须在线程之间保持一定的同步关系,才能使用户能够对独立运行的线程进行有效的控制.为此本文在简要介绍Windows 95中线程的概念及其创建方法后,提出了一种在多线程之间利用 event对象实现事件同步的控制方法.最后还介绍了在不同应用程序之间进行同步事件控制的方法,这种方法使得不同应用程序进行相互间的同步事件控制变得很简单. 关键词:Windows95 线程 同步事件 event 对象 Win32