`

java concurrent (1) - 传统线程互斥和通信

阅读更多
线程互斥是一次只有一个线程执行某段代码,保证数据的一致性。线程通信是指通过notify或notifyAll来唤醒在wait某个对象锁的线程。实现方式是通过synchronized关键字声明。

1. 如果同步代码块在对象方法中,可以实例化一个Object来作为lock的对象,或者用this关键字表示lock这个对象:

synchronized(obj) {
   // code block
}

synchronized(this) {
   // code block
}


2. 如果同步代码块在静态方法中,使用一个静态对象,如当前class的字节码来作为lock的对象:

synchronized(CurrentClass.class) {
   // code block
}


3. synchronized修饰整个方法,这时锁的对象就是当前实例化的对象,保证一次只有一个线程执行这个方法:

public synchronized void warranty() {
   // code segment
}

public synchronized void merchantability() {
   // code segment
}


如果对象的两个或两个以上方法都加了synchronized修饰符,则一次只能由一个线程执行其中的某一个方法。

我们可以把需要互斥执行的代码分别放到这些方法里实现互斥,然后辅以wait和notify实现通信,看下面的例子:

主线程执行100次A代码后,由辅线程执行10次B代码,然后再由主线程执行100次A代码,辅线程10次B代码,如此循环40次。

public class TraditionalConcurrentCommunication {

	public static void main(String[] args) {
		// Ensure to operate the same object
		final Cooperation cooperation = new Cooperation();

		// Main thread
		new Thread(new Runnable() {

			@Override
			public void run() {
				for (int t = 1; t <= 40; t++) {
					try {
						cooperation.first(t);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}

		}).start();

		// Sub thread
		new Thread(new Runnable() {

			@Override
			public void run() {
				for (int t = 1; t <= 40; t++) {
					try {
						cooperation.second(t);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}

		}).start();
	}

	static class Cooperation {
		private boolean bFirst = true;

		public synchronized void first(int times) throws InterruptedException {
			while (!bFirst) { // 使用状态标志防止伪唤醒
				wait(); // 在当前对象上等待被唤醒
			}

			for (int i = 1; i <= 100; i++) {
				System.out.println(Thread.currentThread().getName() + " is executing first() in loop of " + i
						+ " of the " + times + " times");
			}

			bFirst = false;
			notify(); // 通知在当前对象上等待的线程,即Sub thread
		}

		public void second(int times) throws InterruptedException {
			while (bFirst) {
				wait();
			}

			for (int i = 1; i <= 10; i++) {
				System.out.println(Thread.currentThread().getName() + " is executing second() in loop of " + i
						+ " of the " + times + " times");
			}

			bFirst = true;
			notify(); // 通知在当前对象上等待的线程,即Main thread
		}
	}
}


这里把业务逻辑放到一个类的两个方法中,体现了面向对象的编程思想。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics