`
xiaozhouzhou
  • 浏览: 13938 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

线程的同步通信与线程范围内的数据共享问题

 
阅读更多
线程的同步通信与线程范围内的数据共享问题
一、线程的同步通信
什么是线程的同步通信?他有什么作用?这是我们在看到一个新概念时多会想起的两个问题。线程的同步通信就是多个线程在做相关的事或者说在操作同一份数据时,线程之间建立一种互知的通信关系;它的作用是使线程之间能和睦共处,既其中某一线程做完这件事后,再通知另外的线程来做这件事,不出现混乱。如上一篇文章留下的面试问题就是一个很好的线程同步编程案例。下面给出详细的代码,和疑问解释。
public class CommunicationThread {
	final static Lock lock=new Lock();//实例化内部类
	public static void main(String args[]){
		new Thread(new Runnable() {
			public void run() {
				for(int i=1;i<=50;i++){
					lock.son(i);//调用子线程
				}
			}
		}).start();
		for(int i=1;i<=50;i++){
			lock.father(i);//调用父线程
		}
	}
	
	/*
	 * Lock类:将相关的互斥操作放在同一个类中
	 */
	static class Lock{
		boolean flag=true;//两个互斥线程的通信钥匙
		public synchronized void son(int i){
			while(!flag){//判断是否是该线程运行,此处也可用if语句,效果相同					 //但while语句可避免伪唤醒的情况发生,程序更安全。
				try {
					this.wait();//线程等待
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			for(int j=1;j<=10;j++){
				System.out.println("son:"+j+"of current"+i);
			}
			flag=false;
			this.notify();//唤醒等待中的线程
		}
		
		public synchronized void father(int i){
			while(flag){
				try {
					this.wait();//线程等待
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			for(int j=1;j<=100;j++){
				System.out.println("father:"+j+"of current"+i);
			}
			flag=true;
			this.notify();//唤醒等待中的线程
		}
	}
}

疑问:问什么要给已经互斥了的线程加上信息判断?这是为了防止电脑主机CPU介入线程的运行,当子线程运行结束之后本因该父线程运行,这时主机CPU就可能介入,再次让子线程来运行,这样就无法达到预期效果。所以在每个线程运行前都判断一下是否该自己运行了,不是的话就就“等待”,并且“唤醒”另外在等待中的线程。所以线程间的通信技术很有用。
----------------------------分割线-----------------------------------

二、线程范围内的数据数据问题:
这个技术点在java ee和底层框架中运用很多,所以很重要,很有必要去弄懂、弄清楚其中的原理。
下面就讲些我的理解:


上图线程1在运行时,调用A、B、C三个模块或对象,这三个模块处理的又是线程1绑定的同一个数据;线程2在运行时,也调用A、B、C三个模块或对象,这三个模块处理的又是线程2绑定的同一个数据,不再是先前线程1的数据了.这种原理就是线程范围内的数据共享,线程间的数据是不一样的,而线程内部运行的数据却一直是同一份。加入有1000个人同时访问一台服务器,这就得开设1000个线程,如果不运用上述原理,就会很混乱,数据调用出问题。所以,线程范围内的数据共享保证了别的线程无法干涉自己线程内部的数据,即使出了问题,也只是单方面的。
下面给出代码加以参考:
public class ShareData {
	private static int data=0;//静态全局变量
	public static void main(String[] args) {
		for(int i=0;i<2;i++){//创建两个线程
			new Thread(new Runnable(){
				public void run() {
					data=new Random().nextInt();
					System.out.println(Thread.currentThread().getName()
							+" has put data:"+data);
					new A().get();//模块A取得数据
					new B().get();//模块B取得数据
				}
				
			}).start();//线程开启
		}

	}
	//静态模块A
	static class A{
		public void get(){
			System.out.println("A from"+Thread.currentThread().getName()
					+" get data:"+data);
		}
	}
	//静态模块B
	static class B{
		public void get(){
			System.out.println("B from"+Thread.currentThread().getName()
					+"get data:"+data);
		}
	}
}

运行结果:



上面的结果明显不适我们想要的。我们需要的是:模块A、B从第一个线程中取得数据相同而与模块A、B从第二个线程取得的数据不同。为什么得不到我们想要的结果呢?这里就是线程内部的数据共享出了问题,线程1调用的模块A、B取得了线程2的数据。那这个问题该怎么解决呢?
只要对上面的代码稍加处理就可以解决了:
public class ShareData {
	//建立哈希表,存取数据
	private static Map<Thread,Integer> threadData=new HashMap<Thread,Integer>();
	public static void main(String[] args) {
		for(int i=0;i<2;i++){//创建两个线程
			new Thread(new Runnable(){
				public void run() {
					int	data=new Random().nextInt();//取得数据
					System.out.println(Thread.currentThread().getName()
							+" has put data:"+data);
					threadData.put(Thread.currentThread(), data);
					new A().get();//模块A取得数据
					new B().get();//模块B取得数据
				}
				
			}).start();//线程开启
		}

	}
	//静态模块A
	static class A{
		public void get(){
			int data = threadData.get(Thread.currentThread());
			System.out.println("A from"+Thread.currentThread().getName()
					+" get data:"+data);
		}
	}
	//静态模块B
	static class B{
		int data = threadData.get(Thread.currentThread());
		public void get(){
			System.out.println("B from"+Thread.currentThread().getName()
					+"get data:"+data);
		}
	}
}

运行结果:


这时得到的结果就是预期想要的了,各线程间的数据互不影响,线程内部的数据能够共享。解决上述问题除了用哈希表外,还可以用ThreadLocal类,这个类的使用更加方便有效,有兴趣的人,可以尝试使用,下面就不给出参考代码了。
----------------------------------------分割线------------------------
线程同步问题现在告以段落了,以上2篇文章都是我在学习中遇到的疑问及理解,如有不足之处还请包含,同时也希望能给你带来些许帮助。
  • 大小: 33.8 KB
  • 大小: 15.4 KB
  • 大小: 15.6 KB
1
3
分享到:
评论

相关推荐

    MFC线程间通信

    最后,线程同步法是一种更高级的线程间通信方式。MFC提供了各种同步对象,如事件对象(CEvent)、互斥量(CMutex)、信号量(CSemaphore)等。这些对象可以用来控制线程的执行顺序,确保关键资源的独占访问。例如,...

    vc++ multithread多线程教程---线程通信--利用事件对象,线程同步--使用信号量,线程同步--使用互斥量,线程同步--使用临界区

    例如,事件对象适合于线程间的复杂通信和协调,信号量可以控制资源的并发访问数量,互斥量适合于独占资源的访问,而临界区则适用于保护小范围的共享数据。理解并熟练运用这些机制,能够帮助开发者编写出高效且线程...

    线程同步代码集实例

    线程同步是多线程编程中的一个重要概念,它主要用于解决多个线程并发访问共享资源时可能出现的竞争条件问题,确保数据的一致性和完整性。在Windows API中,提供了多种线程同步机制,如Event、Mutex、Semaphore和...

    VC++MFC多线程同步实例

    多线程同步是保证多个线程安全交互的关键技术,避免了数据竞争和死锁等问题。本实例主要探讨了四种主要的同步机制:信号量、互斥锁、事件以及临界资源。 首先,信号量(Semaphore)是一种计数型同步对象,用于控制...

    java线程同步

    Java线程同步是多线程编程中的一个重要概念,它用于解决在并发环境下多个线程对共享资源的访问问题,以防止数据的不一致性。在Java中,线程同步的机制主要包括锁、同步块、同步方法、volatile关键字以及线程通信(如...

    Java多线程同步问题的探究.pdf

    在Web应用和框架中,ThreadLocal被广泛用来存储请求范围内的数据。 在讨论Java多线程同步问题时,JVM的作用也不可忽视。JVM负责管理和调度Java程序中的线程,包括线程的创建、运行、同步、通信以及销毁。JVM中的...

    多线程编程四-线程同步.pdf

    线程同步是多线程编程中不可或缺的概念,主要是为了解决多个线程并发执行时可能出现的数据竞争和资源冲突问题。在多线程环境中,当多个线程试图同时访问和修改共享资源时,如果没有适当的同步机制,可能会导致数据不...

    多线程并发编程-同步与互斥-原⼦变量-并发和⽆锁 数据结构

    在线程的共享资源中,全局变量是在程序的全局范围内定义的变量,堆用于存储线程创建的对象等信息,除此之外,所有线程共享同一块代码段。 5.2 线程⽣命周期 线程的生命周期涵盖了从其创建、执行、到终止的所有阶段...

    c++多线程编程之四——线程的同步

    【线程同步】是多线程编程中一个关键的概念,主要目的是解决多个线程并发访问共享资源时可能出现的问题,如数据不一致、竞态条件等。在C++中,MFC(Microsoft Foundation Classes)框架提供了多种同步对象来帮助...

    Windows多线程编程详解

    线程间通信通常涉及数据共享和消息传递: 1. 全局变量和静态变量:共享内存区域进行通信,需配合同步机制防止数据竞争。 2. 剪贴板:可以用来在不同线程间交换数据。 3. Windows消息队列:通过PostMessage和...

    windows 线程同步编程

    在Windows环境下,线程同步是多线程编程中不可或缺的一部分,它主要负责解决并发操作时的数据一致性问题,防止出现竞态条件。本文将基于提供的文件信息,深入探讨Windows下的线程同步机制,尤其是C#中四种核心的进程...

    主线程和工作线程相互之间的通信示例程序

    全局变量是一种在整个程序范围内都可访问的数据,因此主线程可以通过修改这个全局变量来调整工作线程的执行速度,比如限制每秒处理的计数次数,从而实现对工作负载的动态控制。 同时,工作线程也需要向主线程反馈其...

    Posix线程编程指南

    该指南将详细介绍POSIX线程编程的基本知识点,包括线程创建、线程间通信、线程取消、线程私有数据、线程同步、线程终止和杂项函数等内容。 线程与进程是操作系统中两种不同的执行流。进程是资源管理的基本单位,而...

    深入浅出Win32多线程程序设计之线程控制

    Win32 API提供了丰富的函数和结构来支持线程的创建与管理,例如`CreateThread`用于创建新线程,`WaitForSingleObject`和`WaitForMultipleObjects`用于线程同步,以及`ExitThread`来结束线程。 线程创建: 在Win32 ...

    多线程编程指南.pdf

    - **线程同步**:由于多个线程可能共享同一资源,因此必须通过同步机制防止数据竞争,确保数据的一致性。 #### 基本线程编程实践 - **线程库的使用**:提供了创建、控制和管理线程的API,如POSIX线程库(pthread)...

    java 猜数字游戏,学习线程

    - 随机数生成线程:使用`Random`类生成一个指定范围内的随机整数,并将其存储在一个全局变量中,如`volatile`修饰的`int`类型变量,以确保线程可见性。 - 猜测线程:不断接收用户输入,与随机数进行比较,判断是否...

    张孝祥Java多线程与并发库高级应用笔记

    - **概念**:线程范围内共享变量是指在线程间共享的数据,需小心处理以避免竞态条件和数据不一致性。 - **作用**:允许线程间通信和协作,但需采用适当的同步机制(如`synchronized`关键字、`Lock`接口)以确保数据...

    MFC多线程基础解析及例子

    在多线程环境下,数据共享和资源访问可能导致竞态条件,因此需要线程同步机制来避免冲突。MFC提供了一些同步对象,如: - **CSemaphore**:限制同时访问特定资源的线程数量。 - **CCriticalSection**:一次只允许一...

Global site tag (gtag.js) - Google Analytics