The synchronization point of the thread that can pair and swap elements in pairs. Each thread renders a method on the entry to the exchange method, matches the partner thread, and receives the object of its partner when it returns. Exchanger may be considered as SynchronousQueue a bidirectional form.
In other words, Exchanger provides a switching service that allows atomic exchange of two (multiple) objects, but only a couple succeeds. Let's look at a simple example model.
In the above model, we assume that an empty stack (stack), the top of the stack (top) is of course no element. At the same time we assume a data structure node that contains an element e to be exchanged and a "hole" node to fill. At this point the thread T1 carry node Node1 into the stack (Cas_push), of course, this is the CAS operation, so that the top of the stack is not empty. Thread T2 carry node node2 into the stack, found that there are elements in the stack node1, and found that the Node1 hold (node) is empty, so that their (node2) to fill the node1 of (Cas_fill). The element Node1 is then ejected from the stack (cas_take). In this way, the thread T1 gets the Node1.hold.item that is the Node2 element E2, the thread T2 Node1.item is E1, thus achieving the purpose of the exchange.
The algorithm description is the content of the presentation.
JDK 5 is a exchanger that is implemented with similar ideas. After JDK 6, in order to support multi-threaded multiple objects at the same time exchanger the transformation (in order to support better concurrency), using the idea of Concurrenthashmap, the stack is divided into a lot of fragments (or slot slots), The thread ID (thread.getid ()) hash falls equally on the same slot, which has good throughput on the default 32 slots. Of course, according to the number of CPU cores of the machine has a certain optimization, interested can go to understand the source of the next exchanger.
As for the use of exchanger, there is an example in the JDK document that tells the two threads exchanging data buffers (which can actually still be considered producer/consumer models).
Class Fillandempty {
exchanger<databuffer> Exchanger = new exchanger<databuffer> ();
DataBuffer Initialemptybuffer = a made-up type
DataBuffer Initialfullbuffer =
Class Fillingloop implements Runnable {
public void Run () {
DataBuffer currentbuffer = Initialemptybuffer;
try {
while (Currentbuffer! = null) {
Addtobuffer (Currentbuffer);
if (Currentbuffer.isfull ())
Currentbuffer = Exchanger.exchange (Currentbuffer);
}
} catch (Interruptedexception ex) {handle}
}
}
Class Emptyingloop implements Runnable {
public void Run () {
DataBuffer currentbuffer = Initialfullbuffer;
try {
while (Currentbuffer! = null) {
Takefrombuffer (Currentbuffer);
if (Currentbuffer.isempty ())
Currentbuffer = Exchanger.exchange (Currentbuffer);
}
} catch (Interruptedexception ex) {handle}
}
}
void Start () {
New Thread (New Fillingloop ()). Start ();
New Thread (New Emptyingloop ()). Start ();
}
}
Exchanger realizes is a kind of data shard idea, this is in the big data situation to divide the data into certain fragment and the multi-threaded execution case has certain use value.
Recently has been evasive work busy, update frequency is getting lower, fortunately, now the work still a bit of personal time, later to strive for more updates, at least also to write this album finish.
In layman's Java Concurrency (26): Concurrent container Part one exchanger[Goto]