Java concurrency framework--aqs How to build a synchronizer using Aqs

Source: Internet
Author: User
Tags cas

Aqs's design idea is to provide a template through inheritance that allows you to easily implement a personalized synchronizer based on different scenarios. The core of Synchronizer is to manage a shared state, which can implement different locking mechanisms through the control of State.

AQS design must consider the complex repetitive and easy error of the management of the queue management, and unified control of the process, and exposed to the subclass call method is mainly the operation of shared State method, in order to provide atomic operation of the state. The general subclass of the Synchronizer using AQS provides GetState, SetState, Compareandsetstate three methods, the first two is the normal get and set methods, to use these two methods must ensure that there is no data competition, The Compareandsetstate method provides a hardware-level atomic update of the CAS mode.

for exclusive mode. The definition of the lock acquisition and release process is given to acquire and release two methods, which define the logic of lock acquisition and release. The same time is also provided to the subclass to get and release the lock interface. Its operational logic is able to refer to the previous "lock acquisition and release". How powerful is it to provide a template? The following pseudo-code can be clearly displayed. Note the two methods of Tryacquire and Tryrelease, which are left to the subclasses to personalize the method by which the management of the shared state can define a variety of Synchronizer itself. The management of the queue and the control of the process is not a problem you need to consider.
① lock get template
if (Tryacquire (ARG)) {
    create node
    Use CAs to insert node into the tail of the queue
    while (true) {
    if (Tryacquire (ARG) and node's predecessor node is the head node) {
Set the current node as the head node
    jump out of Loop
}else{
    Use CAs to change the waitstatus identifier of the node precursor to signal
    if (change succeeded)
        suspend current thread  
}
}
② lock Release template
    if (Tryrelease (ARG)) {
Wakes a thread that may be included in a node
}


We can feel that the Synchronizer implements whatever the semantics of the lock. The lock that is generally provided to the user is a higher level implementation implemented with the AQS framework package, providing a more graphic API for users to use more easily and concisely. Instead of giving the user direct access to the AQS frame, for example. Reentrantlock, Semphore, Countdownlatch and so on. These different image locks let you use them better to understand more handy, and not easy to confuse.

However, these locks are implemented by AQS. Aqs Synchronizer is oriented to the control of thread and state, defines the mechanism of thread acquiring state and thread queueing, and so on, it is very good to isolate the focus of the two, the high-level concern is the use of the scene, while the Aqs Synchronizer is concerned with concurrency control.

If you want to implement a self-defining synchronizer, it is officially recommended that the subclass of the integrated Aqs synchronizer be the inner class of the synchronization device, and that the associated operation in the synchronization device only needs to be represented by the corresponding method in the subclass. Use a simple example to see how to implement your own lock, because the Synchronizer is divided into two modes. Exclusive mode and shared mode. So the examples are given accordingly.


① Exclusive mode. The example of exclusive mode is the Banking service form, and if a bank dot has only one service form, then the banking services form can only serve a single person at the same time. Others have to wait in line, so the bank form Synchronizer is an exclusive model.

The first class is the Bank form synchronization appliance class. It follows the recommended practice of using a subclass of an inherited Aqs Synchronizer and appears as a subclass. The second class is a test class, the image is said. There are three people in the bank to do business, each of which is Tom, Jim and Jay, we can use Bankservicewindow to bind them to line up, one by one round to deal with the business and avoid into chaos.
public class Bankservicewindow {
Private final sync sync;
Public Bankservicewindow () {
sync = new sync ();
}
private static class Sync extends Abstractqueuedsynchronizer {
public boolean tryacquire (int acquires) {
if (compareandsetstate (0, 1)) {
Setexclusiveownerthread (Thread.CurrentThread ());
return true;
}
return false;
}
protected Boolean tryrelease (int releases) {
if (getState () = = 0)
throw new Illegalmonitorstateexception ();
Setexclusiveownerthread (NULL);
SetState (0);
return true;
}
}
public void handle () {
Sync.acquire (1);
}
public void Unhandle () {
Sync.release (1);
}
}


public class Bankservicewindowtest {
public static void Main (string[] args) {
Final Bankservicewindow bankservicewindow=new Bankservicewindow ();
Thread Tom=new thread () {
public void Run () {
Bankservicewindow.handle ();
System.out.println ("Tom starts to transact business");
try {
This.sleep (5000);
} catch (Interruptedexception e) {
E.printstacktrace ();
}
System.out.println ("Tom ends The Business");
Bankservicewindow.unhandle ();
}
};
Thread Jim=new thread () {
public void Run () {
Bankservicewindow.handle ();
System.out.println ("Jim begins to transact business");
try {
This.sleep (5000);
} catch (Interruptedexception e) {
E.printstacktrace ();
}
System.out.println ("Jim ends The Business");
Bankservicewindow.unhandle ();
}
};
Thread Jay=new thread () {
public void Run () {
Bankservicewindow.handle ();
System.out.println ("Jay begins to transact business");
try {
This.sleep (5000);
} catch (Interruptedexception e) {
E.printstacktrace ();
}
System.out.println ("Jay ends the Business");
Bankservicewindow.unhandle ();
}
};
Tom.start ();
Jim.start ();
Jay.start ();
}
}
The output results are as follows:
Tom starts to transact business
Tom ends the business process
Jim starts to transact business
Jim ends the business process
Jay starts to transact business
Jay ends Processing business
Obviously Tom, Jim, and Jay are all lined up. But there is no guarantee that the three can be in the order of Tom, Jim, Jay, or Tom, Jay, or Jim. Because in into row once the operation successively is unable to determine, its semantics is guarantees one after another processing.

Assume that there is no synchronizer limit condition. The output will not be pre-measured. Possible for output such as the following:
Jim starts to transact business
Jay starts to transact business
Tom starts to transact business
Jay ends Processing business
Jim ends the business process
Tom ends the business process


Ii Shared mode, the sample shared mode is the same as the Bank service form, along with the development of this dot. Processing business more and more people, a service form has been unable to meet the demand, and then assigned a staff to open another service form, then can serve two people at the same time, but two forms are occupied when the same also must wait in line, such a service form Synchronizer device is a shared type. The first class is a shared-mode synchronization appliance class, which differs from exclusive mode in that the initial value of its state can be freely defined, and that getting and releasing is the reduction of State and the accumulation of operations. The second class is the test class, Tom, Jim and Jay come to the bank again, a two form is very happy, they can two people at the same time, the time is reduced a lot.
public class Bankservicewindows {
Private final sync sync;
public bankservicewindows (int count) {
sync = new sync (count);
}
private static class Sync extends Abstractqueuedsynchronizer {
Sync (int count) {
SetState (count);
}
public int tryacquireshared (int interval) {
for (;;) {
int current = GetState ();
int newcount = current-1;
if (Newcount < 0 | | compareandsetstate (current, newcount)) {
return newcount;
}
}
}
public boolean tryreleaseshared (int interval) {
for (;;) {
int current = GetState ();
int Newcount = current + 1;
if (Compareandsetstate (current, newcount)) {
return true;
}
}
}
}


public void handle () {
Sync.acquireshared (1);
}


public void Unhandle () {
Sync.releaseshared (1);
}


}


public class Bankservicewindowstest {
public static void Main (string[] args) {
Final Bankservicewindows bankservicewindows=new bankservicewindows (2);
Thread Tom=new thread () {
public void Run () {
Bankservicewindows.handle ();
System.out.println ("Tom starts to transact business");
try {
This.sleep (5000);
} catch (Interruptedexception e) {
E.printstacktrace ();
}
System.out.println ("Tom ends The Business");
Bankservicewindows.unhandle ();
}
};
Thread Jim=new thread () {
public void Run () {
Bankservicewindows.handle ();
System.out.println ("Jim begins to transact business");
try {
This.sleep (5000);
} catch (Interruptedexception e) {
E.printstacktrace ();
}
System.out.println ("Jim ends The Business");
Bankservicewindows.unhandle ();
}
};
Thread Jay=new thread () {
public void Run () {
Bankservicewindows.handle ();
System.out.println ("Jay begins to transact business");
try {
This.sleep (5000);
} catch (Interruptedexception e) {
E.printstacktrace ();
}
System.out.println ("Jay ends the Business");
Bankservicewindows.unhandle ();
}
};
Tom.start ();
Jim.start ();
Jay.start ();
}
}
The possible output results are:
Tom starts to transact business
Jay starts to transact business
Jay ends Processing business
Tom ends the business process
Jim starts to transact business
Jim ends the business process
Tom and Jay were almost at the same time to start the business, while Jay ended up with a spare service form Jim came over.
This section is mainly about how to build your own synchronizer using AQS. Moreover, it analyzes the logic of the template of lock acquisition and release, so that you better understand the implementation of AQS, and finally gives a sample of the synchronous implementation of the exclusive mode and the shared mode respectively. I'm sure you'll figure out how these two approaches are achieved. To build a more complex synchronizer, you know where the force is going to go.



Students who like to study Java can make a friend. The following is my number:




Java concurrency framework--aqs How to build a synchronizer using Aqs

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.