"Flume" The CAS operation in Java concurrent programming from the perspective of Flume's monitoring metrics data xxxcounter

Source: Internet
Author: User
Tags cas


As shown in the Red box section, I do stability testing, when the flume run a few days later, I found that the counter value gradually become larger, to a certain value, and then become smaller, there is a cycle of the process, and therefore the desire to produce research, the following to see:

if (Txneventcount = = 0) {        sinkcounter.incrementbatchemptycount ();      } else if (Txneventcount = = batchsize) {        Sinkcounter.incrementbatchcompletecount ();      } else {        sinkcounter.incrementbatchunderflowcount ();      }
Incrementbatchemptycount method, check it in.

Public long Incrementbatchemptycount () {    return increment (counter_batch_empty);  }
protected long increment (String counter) {    return Countermap.get (counter). Incrementandget ();  
Public final long Incrementandget () {for        (;;) {            Long current = Get ();            Long Next = current + 1;            if (Compareandset (current, next))                return next;        }    }
This kind of writing at first glance is very strange, missing a return branch, in fact, it means that when the if condition is false, do nothing, will not return, only if is true, will return

Public Final Boolean compareandset (long expect, long update) {        return Unsafe.compareandswaplong (this, Valueoffset, expect, update);    }
Can not go in here, and then down is the JDK native method is implemented, there is a need to see this link
This is where CAS operates "compare and Swap/set". This means that the value is not changed before set and is assigned only if it is not changed.

For example, when you do a variable + + operation, you have to determine whether the variable itself before doing the + + operation has changed before, this situation will occur in the multi-threaded environment, there is a mechanism for locking can solve the problem, but do not lock, with CAS can also be solved!!

The caller of the above code is unsafe, providing an operation against the volatile variable, which is based on the direct invocation of the CAS action of the CPU.

Prior to JDK 5, the Java language was guaranteed to be synchronized by the Synchronized keyword, which would result in a lock

The lock mechanism has the following issues:

(1) under the multi-thread competition, locking, releasing locks can cause more context switching and scheduling delays, causing performance problems .

(2) a thread holding a lock will cause all other needs for this lock thread Hangs .

(3) If a high-priority thread waits for a thread with a lower priority to release the lock, it causes the priority to be inverted, causing Performance Risk .

Volatile is a good mechanism, but volatile does not guarantee atomicity. Therefore, for synchronization to eventually return to the lock mechanism.

Non-atomic nature of "attached" volatile

First of all, when is the global variable required to have a volatile modifier? For example, if most of our global variables are lock-protected, do we still need volatile? The answer is no, that is, when a global variable is protected by a lock, the global variable does not need to be volatile. There are two reasons: one is that the lock guarantees the serial of the critical section, and the other is the memory barrier in the implementation of the lock, which guarantees that the critical section accesses the global variable to the newest value. It can be concluded, then, that a global variable with no lock protection needs to be modified with the use of volatile, as in the following scenario:
1. global variable int exit_flag = 0;
2. The exit condition for the main loop of thread 1 is to check if Exit_flag is 1 and 1, then exit the main loop;
3. Thread 2 In some cases, modify exit_flag to 1.
In addition, if it is asynchronous, there is no thread 2, and there is a signal processing function that assigns a value of Exit_flag to 1 when the specified signal is received.
At this point, exit_flag need to be modified using volatile. Otherwise, for thread 1 code, if the compiler discovers that there is no place to modify Exit_flag in line 1 code, it is possible to put Exit_flag in the register cache. In this way, every time the condition is checked, it is read from the register, not the exit_flag corresponding memory. This results in a value of 0 per read, which causes Thread1 to fail to exit. Using the volatile modifier exit_flag avoids this optimization by the compiler, forcing each read to be read from memory, which ensures that THREAD1 can read to the latest value and exit when Exit_flag is set to 1 o'clock.

Volatile provides only guaranteed access to the variable, each time it reads the latest value from memory and does not use the register to cache the value-each time it is read from memory
In the modification of the variable, volatile does not provide a guarantee of atomicity. So whether the compiler is directly modifying the memory value or using a register modification is a volatile definition. So, in a word, volatile does not provide a guarantee of atomicity.

An exclusive lock is a pessimistic lock, and synchronized is an exclusive lock that causes all other threads that need to be locked to hang, waiting for the thread that holds the lock to release the lock. Another more effective lock is the optimistic lock. The so-called optimistic lock is that each time without locking but assuming that there is no conflict to complete an operation, if the conflict failed to retry until successful.


Exclusive lock--synchronized

Optimistic lock--cas "compare and Swap/set"

CAS has three operations: current in-memory value V, expected value A, updated value B, only when A==v is updated to B, otherwise nothing

Taking Atomiclong as an example

Public final long Incrementandget () {for        (;;) {            Long current = Get ();            Long Next = current + 1;            if (Compareandset (current, next))                return next;        }    }
The Compareandset method calls the native method to implement the CAS operation, where current is a value obtained before the method, which is a volatile variable defined by get, which is the value read from memory. Then the current value is compared to the value read from memory just before the update, and the equivalent is update to next value, otherwise, nothing is done.
protected long increment (String counter) {    return Countermap.get (counter). Incrementandget ();  
Look at the code in the flume above, Countermap.get (counter) we can understand the memory value "current Value", in the Incrementandget method inside the Current=get () is the expected value, next is the update value

Above part of the content from the network, not the author, please Haihan!

Look Feel free!!

"Flume" The CAS operation in Java concurrent programming from the perspective of Flume's monitoring metrics data xxxcounter

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.