XI, build custom synchronization tool

状态依赖性的管理

  • 条件队列

条件队列就好像烤面包机中通知“面包已烤好”的铃声。If you pay attention to listen to the tone, then when baking cookies can be notified immediately, and then drop the matter at hand (or put the matter at hand done, for example, to read the newspaper) to start tasting bread. If you do not hear the bell (probably out to get the newspaper), then miss a notification message, but returned to the kitchen, can have observed toaster state, if already cooked, then remove the bread, if not already baked, it again ringtones attention.

"Conditions Queue" The name comes from: it enables a set of threads (thread waiting call set) can be waiting for a specific condition becomes true in some way.传统队列的元素是一个个数据,而与之不同的是,条件队列中的元素是一个个正在等待相关条件的线程。

正如每个Java对象都可以作为一个锁,每个对象同样可以作为一个条件队列,并且Object中的wait、notify和notifyAll方法就构成了内部条件队列的API。Built-in lock its internal condition queue object are interrelated, 要调用对象X中条件队列的任何一个方法,必须持有对象X上的锁。because "waiting for the conditions consisting of state" and "Maintenance status consistency" Both of these mechanisms must be closely tied together:只有能对状态进行检查时,才能在某个条件上等待,并且只有能修改状态时,才能从条件等待中释放另一个线程。

Obiect.wait会自动释放锁,并请求操作系统挂起当前线程,从而使其他线程能够获得这个锁并修改对象的状态。When the suspended thread wakes up, it will re-acquire the lock before returning.从直观上来理解,调用wait意味着“我要去休息了,但当发生特定的事情时唤醒我”,而调用通知方法(notify)就意味着“特定的事情发了”。

二、使用条件队列

  • 条件谓词

Operating condition predicate is to become a prerequisite for state-dependent operation. Bounded in the cache, and only when the cache is not empty, take method to perform, or else must wait. To take the method, its condition predicate is the "buffer is not empty", you must first take the method to test the condition predicate before execution. Similarly, the condition predicate put method is "Cache dissatisfied." Condition predicate is an expression consisting of the class of each state variable. BaseBoundedBuffer will count compared with 0 in the test "is not empty cache", will count compared with the size of the cache in the test "cache discontent."

将与条件队列相关联的条件谓词以及在这些条件谓词上等待的操作都写入文档是一个良好的习惯。
在条件等待中存在一种重要的三元关系,包括加锁、wait方法和一个条件谓词。在条件谓 词中包含多个状态变量,而状态变量由一个锁来保护,因此在测试条件谓词之前必须先持有这 个锁。锁对象与条件队列对象(即调用wait和notify等方法所在的对象)必须是同一个对象。

每一次wait调用都会隐士地与特定的掉件谓词关联起来。当调用某个特定条件谓词的wait时,调用者必须已经持有与条件队列相关的锁,并且这个锁必须保护着构成条件谓词的状态变量。

  • 过早唤醒

Although the Trilateral Relations between the locks, condition predicate and condition queue is not complicated, but the wait condition predicate method returns does not necessarily mean that the thread is waiting for the final has become true.

Built-queue conditions may be used with a plurality of condition predicates. When a thread calls notifyAll due wakes up, it does not mean that the condition predicate the thread is waiting for has become true. (It's like a toaster and coffee maker share a ring tone. When ringing, you have to see which device is ringing issued.) Also, wait method also can "pretend" to return, and not due to a thread calls notify .

When performing control to re-enter the code calls wait, it has re-acquired the lock associated with the condition queue. Now is not the predicate condition has become true? perhaps. When a thread calls notifyAll notice, the predicate conditions may have become true, but when re-acquire the lock becomes false again. In the thread wakes to wait to reacquire lock this time, there may be other thread has acquired the lock, and change the shape of the object too. Or, from the condition predicate call wait since become simply not true. You do not know why another thread calls notify or notifyAll, perhaps because another condition predicate associated with the same condition queue became true. "A condition queue associated with more than one condition predicate" is a very common situation.

For all these reasons, every when the thread wakes up from wait, the condition predicate must be tested again if the condition predicate is not true, then continue to wait (or failure). Since the thread is not really the case may be repeatedly wake up in the condition predicate, wait _ This must be called in a loop, and in each iteration all test conditions predicate. Listing shows the standard form of the condition wait.

void stateDependentMethod() throws InterruptedException {
    //必须通过一个锁来保护条件谓词 
    synchronized (lock) {
        while (!conditionPredicate())
            lock.wait();
        //现在对象处于合适的状态
    }
}

When the wait conditions (e.g. Object.wait or Condition.await)

  • Usually have a predicate conditions - including some of the test object state, the thread must first pass before performing these tests.
  • Test condition predicate before calling wait, and tested again when returning from wait in.
  • Call wait in a loop.
  • Be sure to use a queue condition associated lock to protect each of the state variables constituting the predicate condition.
  • When you call, etc. wait, notify or notifyAU method, be sure to hold the lock associated with the condition queue.
  • After checking the condition predicate before the start and the appropriate action, do not release the lock.
  • 丢失的信号

Another form of active fault signal is lost. 丢失的信号是指:线程必须等待一个已经为真的条件,但在开始等待之前没有检査条件谓词。Now, a thread will wait for the event has been sent. This is like a toaster After starting out to get the newspaper, when you are still outside of the toaster when the bell rang, but you did not hear, and therefore will be sitting at the kitchen table waiting for the bell toaster . You might wait a long time. Notice does not like you spread on bread and jam, it does not "adhesion." If the thread A notifies a condition queue, and then thread B waiting in the queue this condition, the thread B will not wake up immediately, but need another notice to wake it up. Like the above program list coding error warning like (for example, do not call the predicate condition is detected before the wait) will result in loss of signal.

  • 通知

Each time while waiting for a condition, it must ensure that the conditions predicate is true ten notification in some way.
There are two methods of notification, i.e., notify and notifyAll condition queue API. 无论调用哪一个,都必须持有与条件队列对象相关联的锁。在调用notify时,JVM会从这个条件队列上等待的多个线程中选择一个来唤醒,而调用notifyAll则会唤醒所有在这个条件队列上等待的线程。The need to hold the lock condition queue object in a call to notify or notifyAll, but at this time if these threads can not wait to re-acquire the lock, it does not return from wait, therefore notice a thread lock should be released as soon as possible, so as to ensure awaiting Tsui plug threads to lift as soon as possible.

Because multiple threads can be based on different conditions predicate waiting on the same condition queue, so if you use notify instead of notifyAll, it would be a dangerous operation because a single notification signal loss can easily lead to similar problems.

Only about two meet conditions in order to use instead of a single notify notifyAll:

  • The same type all waiting threads. Only one condition predicate condition associated queue, and each thread performs the same operations after returning from the wait.
  • Single in single out. Every time notifications on condition variables, can only wake up a thread to execute.

三、显示的Condition对象

Condition is a generalized condition queue built.

public interface Condition {
    void await() throws InterruptedException;

    void awaitUninterruptibly();

    long awaitNanos(long var1) throws InterruptedException;

    boolean await(long var1, TimeUnit var3) throws InterruptedException;

    boolean awaitUntil(Date var1) throws InterruptedException;

    void signal();

    void signalAll();
}

Built-queue conditions some drawbacks. Each has a built-in lock can only be associated with the condition queue. These factors make it impossible to meet the waiting threads of the same type of needs of all in the use of notifyAIl. To prepare an object having a plurality of concurrent condition predicates, in addition to or want to get more control over the conditions outside the queue visibility can use explicit rather than built-Lock and Condition lock queue and conditions, this is a kind of more flexible options.

A Condition and a Lock associate together as a cohort and conditions associated with a built-in lock, like, 要创建一个Condition,可以在相关联的Lock上调用Lock.newCondition方法。just as Lock offers a much richer functionality than the built-in lock, Condition same conditions than the built-in queues provide a richer functions: each lock may be multiple wait condition wait may be interrupted or not interrupted, based on the waiting time, and a fair or non-fair queue operations.

The built-in condition is different queue for each Lock, you can have any number of Condition objects. Condition object inherits the fairness of the relevant Lock object for fair locks, the thread is released from Condition.await in accordance with the FIFO order.

Special attention: Condition in a subject, and wait, notify, and notifyAll methods respectively corresponding to await, signal and signalAll. However, Condition of the Object was extended so that it also contains wait and notify methods. Be sure to use the correct version -wait and signal.

4、AbstractQueuedSynchronizer

http://ifeve.com/introduce-abstractqueuedsynchronizer/

5、原子变量类

A total of 12 atomic variable classes, can be divided into four groups: Scalar (the Scalar), update the class, class variables and composite array class. The most common type is a scalar variable atomic categories: AtomicInteger, AtomicLong, AtomicBoolean and AtomicReference.

Guess you like

Origin blog.csdn.net/qq_27870421/article/details/90583736