代码解说多线程互斥与同步通信问题

参考

张孝详系列

场景

编写一个程序:子线程连说 3 次  “ 你愿意吗?” ,接着主线程连续回答 10次 “我愿意” ,然后子线程再说3次“你愿意吗?”,主

线程回答“我愿意” 10次 。。。 轮流如此往复执行 10次。

分析

“连说 3 次”,“连续回答” 意味着互斥-主线程执行的时候,子线程不能执行;子线程执行的时候,主线程不能执行。

“轮流往复”意味着同步-主线程执行完一次任务(即回答10次“我愿意”),后不能继续执行,需要等待子线程执行完任务后才执行。

实验

一、线程互斥与同步通信
package cool.pengych.java.thread;

/**
 *  线程互斥与同步通信问题
 * @author pengyucheng
 */
public class ThreadCommunication
{
	/**
	 * 业务类
	 */
	final class Business
	{
		private boolean iSubExecute = true;

		//子线程执行
		public synchronized void sub()
		{
			while(!iSubExecute)// 这里 if 也行,但是while 使程序更健壮
			{
				try
				{
					this.wait();
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}
			}
			for(int i=0;i<3;i++)
			{
				System.out.println("你愿意吗?");
			}
			iSubExecute = false;
			this.notify();
		}

		//主线程执行
		public synchronized void main()
		{
			while(iSubExecute) // if 也行,但是while 使程序更健壮
			{
				try
				{
					this.wait();
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}
			}
			for(int i=0;i<10;i++)
			{
				System.out.println("我愿意!");
			}
			iSubExecute = true;
			this.notify();
		}
	}
	public static void main(String[] args)
	{
		Business business = new ThreadCommunication().new Business();
		new Thread(new Runnable()
		{
			@Override
			public void run()
			{
				for(int i = 0;i<10;i++)
				{
					business.sub();
				}
			}
		}).start();

		for(int i = 0;i<10;i++)
		{
			business.main();
		}
	}
}
执行结果

你愿意吗?
你愿意吗?
你愿意吗?
我愿意!
我愿意!
我愿意!
我愿意!
我愿意!
我愿意!
我愿意!
我愿意!
我愿意!
我愿意!
你愿意吗?
你愿意吗?
你愿意吗?
我愿意!
我愿意!
我愿意!
我愿意!
我愿意!
我愿意!
我愿意!
我愿意!
我愿意!
我愿意!
 。。。
二、对象锁互斥的两种表现形式
package cool.pengych.java.thread;
/**
 * 多线程同步:对象锁
 * 总结:java多线程同步本质上是通过对象锁-多个线程&同一个对象;形式上有代码块同步,方法同步.
 * @author pengyucheng
 */
public class ResourceShare
{
	private static Object lock = new Object();

	   /**
		 * 通过 this关键字同步
		 * @param name
		 */
		public  synchronized void output(String name)
		{
				for(int i=0;i<name.length();i++)
				{
					System.out.print(name.charAt(i));
				}
				System.out.println();
		}

		/**
		  *静态方法通过 ResourceShare.class 关键字同步 (静态方法关联的只有类的字节码对象了)
		  * @param name
		  */
		public  static synchronized void output2(String name)
		{
				for(int i=0;i<name.length();i++)
				{
					System.out.print(name.charAt(i));
				}
				System.out.println();
	   }

	/**
	 *  测试方法
	 * @param args
	 */
	public static void main(String[] args)
	{
		ResourceShare rs = new ResourceShare();
		new Thread(new Runnable() {
			@Override
			public void run()
			{
				try
				{
					Thread.sleep(1000);
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				while(true)
				{
					// new ResourceShare().new Outputer().output("pengyucheng");
					ResourceShare.output2("pengyucheng");
				}
			}
		}).start();

		new Thread(new Runnable() {
			@Override
			public void run()
			{
				try
				{
					Thread.sleep(1000);
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				while(true)
				{
					// new ResourceShare().new Outputer().output2("**tianlai**");
					rs.output2("**tianlai**");
				}
			}
		}).start();
	}

   class Outputer
	{
		/**
		 * 对象锁 lock: 这个对象必须对要同步的线程来说是同一线程
		 * 若去掉 static关键字  private Object lock = new Object(); 则本例不能同步
		 * @param name
		 */
		public void output(String name)
		{
			synchronized(lock) //代码块同步
			{
				for(int i=0;i<name.length();i++)
				{
					System.out.print(name.charAt(i));
				}
				System.out.println();
			}
		}

		/**
		 * 通过 this关键字同步
		 * @param name
		 */
		public synchronized void output2(String name)
		{
				for(int i=0;i<name.length();i++)
				{
					System.out.print(name.charAt(i));
				}
				System.out.println();
		}
	}
}
时间: 2025-01-22 07:31:47

代码解说多线程互斥与同步通信问题的相关文章

【转】Linux平台上用C++实现多线程互斥锁

原作者:chexlong 原文地址:http://blog.csdn.net/chexlong/article/details/7058283 在上篇用C++实现了Win32平台上的多线程互斥锁,这次写个Linux平台上的,同样参考了开源项目C++ Sockets的代码,在此对这些给开源项目做出贡献的斗士们表示感谢! 下边分别是互斥锁类和测试代码,已经在Fedora 13虚拟机上测试通过. Lock.h [cpp] view plaincopy #ifndef _Lock_H #define _

linux多线程-互斥&amp;条件变量与同步

多线程代码问题描述 我们都知道,进程是操作系统对运行程序资源分配的基本单位,而线程是程序逻辑,调用的基本单位.在多线程的程序中,多个线程共享临界区资源,那么就会有问题: 比如 #include <pthread.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> int g_val = 10; void * test1(void* args) { g_val = 20; printf(&

多线程互斥--mutex

多线程之线程同步Mutex (功能与Critial Sections相同,但是属于内核对象,访问速度较慢,可以被不同进程调用) 一 Mutex 互斥对象(mutex)内核对象能够确保线程拥有对单个资源的互斥访问权.实际上互斥对象是因此而得名的.互斥对象包含一个使用数量,一个线程ID和一个递归计数器. 互斥对象的行为特性与关键代码段相同,但是互斥对象属于内核对象,而关键代码段则属于用户方式对象.这意味着互斥对象的运行速度比关键代码段要慢.但是这也意味着不同进程中的多个线程能够访问单个互斥对象,并且

多线程互斥--mutex(二)

不知道大家对多线程或多进程间的同步互斥的控制机制了解的怎么样,其实有很多种方法可以实现这个目的,但是这些方法其实由4种最基本的方法实现.这4种最基本的方法具体定义如下:在这有讲得不对的地方欢迎各位扔砖,希望不会误导大家. 1.临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问. 2.互斥量:为协调共同对一个共享资源的单独访问而设计的. 3.信号量:为控制一个具有有限数量用户资源而设计. 4.事  件:用来通知线程有一些事件已发生,从而启动后继任务的开始. 临界区(Cr

python高性能代码之多线程优化

以常见的端口扫描器为实例 端口扫描器的原理很简单,操作socket来判断连接状态确定主机端口的开放情况. import socket def scan(port): s = socket.socket() if s.connect_ex(('localhost', port)) == 0: print port, 'open' s.close() if __name__ == '__main__': map(scan,range(1,65536)) 这是一个socket扫描器的基本代码. 但是如

多线程互斥-读写者问题

互斥量(mutex) 互斥锁创建 有两种方法创建互斥锁,静态方式和动态方式.POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER 来静态初始化互斥锁,方法如下: pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;在LinuxThreads实现中, pthread_mutex_t是一个结构,而PTHREAD_MUTEX_INITIALIZER则是一个结构常量. 动态方式是采用pthread_mutex_init()函数来初始化互斥锁

多线程-互斥变量

第一个 CreateMutex 函数功能:创建互斥量(注意与事件Event的创建函数对比) 函数原型: HANDLE  CreateMutex( LPSECURITY_ATTRIBUTESlpMutexAttributes, BOOLbInitialOwner, LPCTSTRlpName ); 函数说明: 第一个参数表示安全控制,一般直接传入NULL. 第二个参数用来确定互斥量的初始拥有者.如果传入TRUE表示互斥量对象内部会记录创建它的线程的线程ID号并将递归计数设置为1,由于该线程ID非零

c#实现每隔一段时间执行代码(多线程)

总结以下三种方法,实现c#每隔一段时间执行代码: 方法一:调用线程执行方法,在方法中实现死循环,每个循环Sleep设定时间: 方法二:使用System.Timers.Timer类: 方法三:使用System.Threading.Timer: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

代码解说Android Scroller、VelocityTracker

在编写自己定义滑动控件时经常会用到Android触摸机制和Scroller及VelocityTracker.Android Touch系统简单介绍(二):实例具体解释onInterceptTouchEvent与onTouchEvent的调用过程对Android触摸机制须要用到的函数进行了具体的解释.本文主要介绍两个重要的类:Scroller及VelocityTracker.利用上述知识,最后给出了一个自己定义滑动控件的demo,该demo类似于ImageGallery. ImageGallery