`
daojin
  • 浏览: 690378 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Java 多线程编程之 notify notifyAll wait lock unlock 算法

 
阅读更多
写了一个类来理解java 同步机制的算法。这个类并不适合实战,而仅仅是算法层面进行理解。

package multithread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * The above specifications allow us to determine several properties having to
 * do with the interaction of waits, notification, and interruption.
 * 
 * If a thread is both notified and interrupted while waiting, it may either:
 * 
 * return normally from wait, while still having a pending interrupt (in other
 * words, a call to Thread.interrupted would return true)
 * 
 * return from wait by throwing an InterruptedException
 * 
 * The thread may not reset its interrupt status and return normally from the
 * call to wait.
 * 
 * Similarly, notifications cannot be lost due to interrupts. Assume that a set
 * s of threads is in the wait set of an object m, and another thread performs a
 * notify on m. Then either:
 * 
 * at least one thread in s must return normally from wait, or
 * 
 * all of the threads in s must exit wait by throwing InterruptedException
 * 
 * Note that if a thread is both interrupted and woken via notify, and that
 * thread returns from wait by throwing an InterruptedException, then some other
 * thread in the wait set must be notified.
 * 
 * @author wa505
 *
 */
public class Monitor {

	private AtomicBoolean mLock = new AtomicBoolean();

	private volatile Thread mHeldThread;

	private volatile int mHeldCount;

	/**
	 * Every object, in addition to having an associated monitor, has an associated
	 * wait set. A wait set is a set of threads. When an object is first created,
	 * its wait set is empty. Elementary actions that add threads to and remove
	 * threads from wait sets are atomic. Wait sets are manipulated solely through
	 * the methods Object.wait, Object.notify, and Object.notifyAll. Wait set
	 * manipulations can also be affected by the interruption status of a thread,
	 * and by the Thread class's methods dealing with interruption. Additionally,
	 * the Thread class's methods for sleeping and joining other threads have
	 * properties derived from those of wait and notification actions.
	 */
	private List<Waitor> mWaitSet = new ArrayList<>();

	private static class Waitor {
		Thread thread;
		int waitCount;
	}

	private boolean isInWaitingSet() {
		Thread thread = Thread.currentThread();
		synchronized (mWaitSet) {
			for (Waitor waitor : mWaitSet) {
				if (waitor.thread == thread) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Notification actions occur upon invocation of methods notify and notifyAll.
	 * 
	 * Let thread t be the thread executing either of these methods on object m, and
	 * let n be the number of lock actions by t on m that have not been matched by
	 * unlock actions. One of the following actions occurs:
	 * 
	 * If n is zero, then an IllegalMonitorStateException is thrown.
	 * 
	 * This is the case where thread t does not already possess the lock for target
	 * m.
	 * 
	 * If n is greater than zero and this is a notify action, then if m's wait set
	 * is not empty, a thread u that is a member of m's current wait set is selected
	 * and removed from the wait set.
	 * 
	 * There is no guarantee about which thread in the wait set is selected. This
	 * removal from the wait set enables u's resumption in a wait action. Notice,
	 * however, that u's lock actions upon resumption cannot succeed until some time
	 * after t fully unlocks the monitor for m.
	 * 
	 * If n is greater than zero and this is a notifyAll action, then all threads
	 * are removed from m's wait set, and thus resume.
	 * 
	 * Notice, however, that only one of them at a time will lock the monitor
	 * required during the resumption of wait.
	 * 
	 * 
	 */
	public void snotifyAll() {
		if (Thread.currentThread() == mHeldThread) {
			if (mHeldCount > 0) {
				synchronized (mWaitSet) {
					mWaitSet.clear();
				}
			}
		}
	}

	public void snotify() {
		if (Thread.currentThread() == mHeldThread) {
			if (mHeldCount > 0) {
				synchronized (mWaitSet) {
					mWaitSet.remove(0);
				}
			}
		}
	}

	/**
	 * Wait actions occur upon invocation of wait(), or the timed forms wait(long
	 * millisecs) and wait(long millisecs, int nanosecs).
	 * 
	 * A call of wait(long millisecs) with a parameter of zero, or a call of
	 * wait(long millisecs, int nanosecs) with two zero parameters, is equivalent to
	 * an invocation of wait().
	 * 
	 * A thread returns normally from a wait if it returns without throwing an
	 * InterruptedException.
	 * 
	 * Let thread t be the thread executing the wait method on object m, and let n
	 * be the number of lock actions by t on m that have not been matched by unlock
	 * actions. One of the following actions occurs:
	 * 
	 * If n is zero (i.e., thread t does not already possess the lock for target m),
	 * then an IllegalMonitorStateException is thrown.
	 * 
	 * If this is a timed wait and the nanosecs argument is not in the range of
	 * 0-999999 or the millisecs argument is negative, then an
	 * IllegalArgumentException is thrown.
	 * 
	 * If thread t is interrupted, then an InterruptedException is thrown and t's
	 * interruption status is set to false.
	 * 
	 * Otherwise, the following sequence occurs:
	 * 
	 * Thread t is added to the wait set of object m, and performs n unlock actions
	 * on m.
	 * 
	 * Thread t does not execute any further instructions until it has been removed
	 * from m's wait set. The thread may be removed from the wait set due to any one
	 * of the following actions, and will resume sometime afterward:
	 * 
	 * A notify action being performed on m in which t is selected for removal from
	 * the wait set.
	 * 
	 * A notifyAll action being performed on m.
	 * 
	 * An interrupt action being performed on t.
	 * 
	 * If this is a timed wait, an internal action removing t from m's wait set that
	 * occurs after at least millisecs milliseconds plus nanosecs nanoseconds elapse
	 * since the beginning of this wait action.
	 * 
	 * An internal action by the implementation. Implementations are permitted,
	 * although not encouraged, to perform "spurious wake-ups", that is, to remove
	 * threads from wait sets and thus enable resumption without explicit
	 * instructions to do so.
	 * 
	 * Notice that this provision necessitates the Java coding practice of using
	 * wait only within loops that terminate only when some logical condition that
	 * the thread is waiting for holds.
	 * 
	 * Each thread must determine an order over the events that could cause it to be
	 * removed from a wait set. That order does not have to be consistent with other
	 * orderings, but the thread must behave as though those events occurred in that
	 * order.
	 * 
	 * For example, if a thread t is in the wait set for m, and then both an
	 * interrupt of t and a notification of m occur, there must be an order over
	 * these events. If the interrupt is deemed to have occurred first, then t will
	 * eventually return from wait by throwing InterruptedException, and some other
	 * thread in the wait set for m (if any exist at the time of the notification)
	 * must receive the notification. If the notification is deemed to have occurred
	 * first, then t will eventually return normally from wait with an interrupt
	 * still pending.
	 * 
	 * Thread t performs n lock actions on m.
	 * 
	 * If thread t was removed from m's wait set in step 2 due to an interrupt, then
	 * t's interruption status is set to false and the wait method throws
	 * InterruptedException.
	 * 
	 * 
	 * 
	 * 
	 * 
	 * Interruption actions occur upon invocation of Thread.interrupt, as well as
	 * methods defined to invoke it in turn, such as ThreadGroup.interrupt.
	 * 
	 * Let t be the thread invoking u.interrupt, for some thread u, where t and u
	 * may be the same. This action causes u's interruption status to be set to
	 * true.
	 * 
	 * Additionally, if there exists some object m whose wait set contains u, then u
	 * is removed from m's wait set. This enables u to resume in a wait action, in
	 * which case this wait will, after re-locking m's monitor, throw
	 * InterruptedException.
	 * 
	 * Invocations of Thread.isInterrupted can determine a thread's interruption
	 * status. The static method Thread.interrupted may be invoked by a thread to
	 * observe and clear its own interruption status.
	 */
	public void swait() {
		if (Thread.currentThread() == mHeldThread) {
			if (mHeldCount > 0) {
				Waitor w = new Waitor();
				w.thread = mHeldThread;
				w.waitCount = mHeldCount;
				synchronized (mWaitSet) {
					mWaitSet.add(w);
				}
				for (int i = 0; i < mHeldCount; ++i) {
					unLock();
				}
				while (isInWaitingSet()) {
					try {
						Thread.sleep(0);
					} catch (InterruptedException e) {
						mWaitSet.remove(w);
					}
				}
				for (int i = 0; i < w.waitCount; ++i) {
					lock();
				}
			}
		}
	}

	/**
	 * <p>
	 * The Java programming language provides multiple mechanisms for communicating
	 * between threads. The most basic of these methods is synchronization, which is
	 * implemented using monitors. Each object in Java is associated with a monitor,
	 * which a thread can lock or unlock. Only one thread at a time may hold a lock
	 * on a monitor. Any other threads attempting to lock that monitor are blocked
	 * until they can obtain a lock on that monitor. A thread t may lock a
	 * particular monitor multiple times; each unlock reverses the effect of one
	 * lock operation.
	 * </p>
	 * <p>
	 * The synchronized statement (§14.19) computes a reference to an object; it
	 * then attempts to perform a lock action on that object's monitor and does not
	 * proceed further until the lock action has successfully completed. After the
	 * lock action has been performed, the body of the synchronized statement is
	 * executed. If execution of the body is ever completed, either normally or
	 * abruptly, an unlock action is automatically performed on that same monitor.
	 * </p>
	 * <p>
	 * A synchronized method (§8.4.3.6) automatically performs a lock action when it
	 * is invoked; its body is not executed until the lock action has successfully
	 * completed.
	 * <li>If the method is an instance method, it locks the monitor associated with
	 * the instance for which it was invoked (that is, the object that will be known
	 * as this during execution of the body of the method).
	 * <li>If the method is static, it locks the monitor associated with the Class
	 * object that represents the class in which the method is defined.
	 * <li>If execution of the method's body is ever completed, either normally or
	 * abruptly, an unlock action is automatically performed on that same monitor.
	 * </p>
	 * <p>
	 * The Java programming language neither prevents nor requires detection of
	 * deadlock conditions. Programs where threads hold (directly or indirectly)
	 * locks on multiple objects should use conventional techniques for deadlock
	 * avoidance, creating higher-level locking primitives that do not deadlock, if
	 * necessary.
	 * </p>
	 * <p>
	 * Other mechanisms, such as reads and writes of volatile variables and the use
	 * of classes in the java.util.concurrent package, provide alternative ways of
	 * synchronization.
	 * </p>
	 */
	public void lock() {
		if (Thread.currentThread() != mHeldThread) {
			while (!mLock.compareAndSet(false, true)) {
				try {
					Thread.sleep(0);
				} catch (InterruptedException e) {

				}
			}
			mHeldThread = Thread.currentThread();
			mHeldCount++;
		} else {
			mHeldCount++;
		}
	}

	public void unLock() {
		if (Thread.currentThread() == mHeldThread) {
			if (mHeldCount > 0) {
				mHeldCount--;
				if (mHeldCount == 0) {
					mHeldThread = null;
					mLock.getAndSet(false);
				}
			}
		}
	}
}


0
0
分享到:
评论

相关推荐

    源码—Java多线程5—死锁和wait notify notifyAll

    源码—Java多线程5—死锁和wait notify notifyAll

    JAVA多线程编程技术PDF

    Java提供了wait(), notify()和notifyAll()方法,这些方法用于在线程间交换信息,但必须在同步块中使用,以防止死锁和其他并发问题。此外,还有java.util.concurrent工具包,包含如BlockingQueue等高级并发结构,它们...

    汪文君JAVA多线程编程实战(完整不加密)

    《汪文君JAVA多线程编程实战》是一本专注于Java多线程编程的实战教程,由知名讲师汪文君倾力打造。这本书旨在帮助Java开发者深入理解和熟练掌握多线程编程技术,提升软件开发的效率和质量。在Java平台中,多线程是...

    java 多线程编程实战指南(核心 + 设计模式 完整版)

    《Java多线程编程实战指南》这本书深入浅出地讲解了Java多线程的核心概念和实战技巧,分为核心篇和设计模式篇,旨在帮助开发者掌握并应用多线程技术。 1. **线程基础** - **线程的创建**:Java提供了两种创建线程...

    Java多线程编程核心技术_完整版_java_

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要通过继承Thread类或实现Runnable接口来实现。本教程《Java多线程编程核心技术》将...

    Java 同步方式 wait和notify/notifyall

    总结一下,`wait()`, `notify()`, 和 `notifyAll()` 是Java多线程编程中的核心工具,它们与`synchronized`关键字一起,为线程间的协作提供了强大的支持。理解并熟练掌握这些概念,对于编写高效、安全的多线程程序至...

    Java多线程编程实战指南-核心篇

    《Java多线程编程实战指南-核心篇》是一本深入探讨Java并发编程的书籍,旨在帮助读者掌握在Java环境中创建、管理和同步线程的核心技术。Java的多线程能力是其强大之处,使得开发者能够在同一时间执行多个任务,提高...

    Java多线程编程

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要通过`Thread`类和并发工具来实现,接下来我们将深入探讨这些关键知识点。 1. **...

    java多线程编程

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要通过继承Thread类或实现Runnable接口来实现。本教程将深入探讨Java多线程的各个方面...

    java 多线程编程指南

    Java提供了wait()、notify()和notifyAll()方法,这些方法与synchronized配合使用,可以让线程在特定条件下等待或唤醒。另外,Java并发包(java.util.concurrent)提供了更高级的并发工具,如Semaphore(信号量)、...

    Java多线程wait和notify

    Java多线程编程是开发高并发应用的关键技术之一,它允许程序同时执行多个任务,提高系统资源利用率。在Java中,`wait()` 和 `notify()` 方法是实现线程间通信和协作的重要工具,它们属于 `java.lang.Object` 类,这...

    深入学习:Java多线程编程

    《深入学习:Java多线程编程》是一本专注于Java并发技术的专业书籍,旨在帮助开发者深入理解和熟练运用Java中的多线程编程。Java多线程是Java编程中的核心部分,尤其在现代高性能应用和分布式系统中不可或缺。理解并...

    java多线程编程实例 (源程序)

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程可以通过实现Runnable接口或继承Thread类来创建。下面我们将深入探讨Java多线程编程的...

    【JAVA多线程】多线程编程核心技术学习资料

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在现代计算机系统中,多线程技术尤其关键,因为它们能够充分利用多核处理器的能力。这份"Java多线程编程...

    Java多线程编程深入详解.docx

    线程通信机制用于实现多线程之间的数据交换,例如wait、notify、notifyAll方法等。 线程初探总结 在本章中,我们探讨了多线程编程的基础知识,包括进程和线程的概念、Java对多线程的支持、第一个多线程程序等。下...

    《Java多线程编程实例》随书源码

    《Java多线程编程实例》这本书深入浅出地探讨了Java中的多线程编程,通过丰富的实例帮助读者理解和掌握这一复杂主题。随书源码提供了实际操作的机会,以便读者能够亲手实践书中的示例,加深理解。 1. **线程创建...

    Java多线程编程核心技术.zip

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,提升系统效率。在Java中,实现多线程主要有两种方式:继承Thread类和实现Runnable接口。本资料"Java多线程编程核心技术.zip"深入探讨了这些...

    浅谈java多线程wait,notify

    在Java多线程编程中,wait和notify是两个非常重要的机制,用于实现线程之间的通信和同步。在本文中,我们将通过示例代码详细介绍Java多线程wait和notify的使用,帮助读者更好地理解和掌握这两个机制。 wait机制 在...

    Java多线程编程实例

    本书“Java多线程编程实例”深入浅出地讲解了如何在Java环境中实现多线程操作,尽管出版时间较早,但其内容的经典性和实用性使其在现代开发中仍具有极高的参考价值。 首先,我们要理解Java中的线程是如何创建的。...

Global site tag (gtag.js) - Google Analytics