Java thread security synchronized, asynchronous ynchronized

Source: Internet
Author: User

Java thread security synchronized, asynchronous ynchronized
I. thread security issues:

Principles of concurrent programming: the purpose of designing concurrent programming is to make the program more efficient, but data consistency (data accuracy) cannot occur, if a concurrent program cannot guarantee the accuracy of the most basic execution results, then concurrent programming has no significance.

Why is the data incorrect:

If a resource (variable, object, file, database) can be used in multiple threads at the same time, data inconsistency may occur, that is, thread security issues. Such resources are called shared resources or critical zones.

For example:

A shared variable m. Now there are two threads simultaneously performing the accumulate operation on it, each executing 10000 times, so what I expect is 20000, but this is not actually the case. Check the Code:

Package com. jalja. base. threadTest; public class SynchronizedTest implements Runnable {private static volatile int m = 0; public static void main (String [] args) {Runnable run = new SynchronizedTest (); thread thread1 = new Thread (run); Thread thread2 = new Thread (run); thread1.start (); thread2.start (); try {// join () make the main thread wait until the execution of the Connection ends and continue to execute the following code thread1.join (); thread2.join ();} catch (InterruptedException e) {e. printStackTrace ();} System. out. println ("m final result:" + m) ;}public void run () {for (int I = 0; I <10000; I ++) {m ++ ;}}}

No matter how many times m is run, it is always less than 20000. Why is such a result? Before thread thread1 writes m ++ results to the memory, thread thread2 has read m values from the memory and performs ++ operations on this value (over time value, finally, write m = 1 to the memory (it may overwrite the m = 1 value calculated by thread1, or thread1 may overwrite the value of thread2 ). This result is inevitable.
How can we control the data accuracy caused by multi-threaded operations on shared data? The "serialize access to critical resources" Scheme means that at the same time, only one thread can access critical resources, also known as synchronous mutex access, that is to say, to ensure that our shared resources can only be used by one thread at a time. Once this resource is used by a thread, other threads will not have the right to use it. Java provides two methods for Synchronous mutex access: synchronized and Lock.

2. synchronized for mutex access (synchronous method or synchronization block)

Mutex lock: As the name implies, it is the lock for mutex access.

For example, if a thread adds a mutex lock to a critical resource, other threads can only wait when it accesses the critical resource.

In Java, each object has a lock tag (monitor), also known as a monitor. When multiple threads access an object at the same time, only the thread that owns the lock can access the object.

In Java, you can use the synchronized keyword to mark a method or code block to be synchronized. When a thread calls the synchronized Method of the object or accesses the synchronized code block, this thread acquires the Lock of this object. Other threads cannot access this method for the moment. This thread will release the Lock of this object only after the method is executed or the code block is executed, other threads can execute this method or code block. In this way, only one thread can access critical resources at the same time.

Synchronized usage:

1. synchronous code block

synchronized(synObject) {             }

Usage: apply synchronized to an attribute of a given object or class. Therefore, whenever a thread executes this code block, the thread will first request to obtain the lock of the object synObject, if the lock has been occupied by other threads, the new thread can only wait, so that other threads cannot access the code block at the same time.

Package com. jalja. base. threadTest; public class SynchronizedTest implements Runnable {private static volatile int m = 0; public static void main (String [] args) {Runnable run = new SynchronizedTest (); thread thread1 = new Thread (run); Thread thread2 = new Thread (run); thread1.start (); thread2.start (); try {// join () make the main thread wait until the execution of the Connection ends and continue to execute the following code thread1.join (); thread2.join ();} catch (InterruptedException e) {e. printStackTrace ();} System. out. println ("m final result:" + m);} public void run () {synchronized (this) {for (int I = 0; I <10000; I ++) {m ++ ;}}}}

This Code uses the current object as the mutex lock. Next we use an attribute of the class as the mutex lock.

Package com. jalja. base. threadTest; public class SynchronizedTest implements Runnable {private static volatile int m = 0; privateObject object = new Object ();Public static void main (String [] args) {Runnable run = new SynchronizedTest (); Thread thread1 = new Thread (run); Thread thread2 = new Thread (run ); thread1.start (); thread2.start (); try {// join () causes the main thread to wait until the execution of the connected thread ends and continue to execute the following code thread1.join (); thread2.join ();} catch (InterruptedException e) {e. printStackTrace ();} System. out. println ("m final result:" + m);} public void run () {synchronized (Object) {For (int I = 0; I <10000; I ++) {m ++ ;}}}}

1. Synchronization Method

Package com. jalja. base. threadTest; public class SynchronizedTest implements Runnable {private static int m = 0; public static void main (String [] args) {Runnable run = new SynchronizedTest (); thread thread1 = new Thread (run); Thread thread2 = new Thread (run); thread1.start (); thread2.start (); try {// join () make the main thread wait until the execution of the Connection ends and continue to execute the following code thread1.join (); thread2.join ();} catch (InterruptedException e) {e. printStackTrace ();} System. out. println ("m final result:" + m);} public synchronized void run () {for (int I = 0; I <10000; I ++) {m ++ ;}}}

In this Code, synchronzied acts on an instance method, that is, when the thread enters the run () method, it must obtain the current object instance lock. In this example, the object instance lock is run. Here we will remind you to take a closer look at the implementation of the main function in the three sections of code. Here we use Runnable to create two threads, and both threads point to the same Runnable interface instance, in this way, the two threads can use the same object lock during work to ensure thread security.

An incorrect understanding:

Package com. jalja. base. threadTest; public class SynchronizedTest implements Runnable {private static int m = 0; public static void main (String [] args) {Thread thread1 = new Thread (new SynchronizedTest ()); thread thread2 = new Thread (new SynchronizedTest (); thread1.start (); thread2.start (); try {// join () make the main thread wait until the execution of the Connection ends and continue to execute the following code thread1.join (); thread2.join ();} catch (InterruptedException e) {e. printStackTrace ();} System. out. println ("m final result:" + m);} public synchronized void run () {for (int I = 0; I <10000; I ++) {m ++ ;}}}

The running result of this Code is incorrect. Please refer to the implementation method of the main function. Use Runnable to create two threads, but the two threads have their own Runnable instances, therefore, when the thread1 thread enters the synchronization method, it is added with its own object instance lock, while thread2 is concerned with its own instance lock when entering the synchronization method, the two threads have different object instance locks, so they cannot meet the mutex requirement.


Slightly changed:

Package com. jalja. base. threadTest; public class SynchronizedTest implements Runnable {private static int m = 0; public static void main (String [] args) {Thread thread1 = new Thread (new SynchronizedTest ()); thread thread2 = new Thread (new SynchronizedTest (); thread1.start (); thread2.start (); try {// join () make the main thread wait until the execution of the Connection ends and continue to execute the following code thread1.join (); thread2.join ();} catch (InterruptedException e) {e. printStackTrace ();} System. out. println ("m final result:" + m) ;}public void run () {for (int I = 0; I <10000; I ++) {count () ;}} public static synchronized void count () {m ++ ;}}

The processing result is what I want. Here we encapsulate the code for processing the business into a static synchronization method. What we need to access this synchronization method now is the lock of the current class, classes only have one copy in the memory, so they use the same lock in any case.

 

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.