Synchronized and Lock of thread safety and data synchronization

Source: Internet
Author: User
Tags object object

This demo download portal is written in front

This article is all about the Android Open Source Network framework Nohttp core Point, of course, thread, multi-threading, data security is in Java, in order to run fast we use a Java project to explain.

Why ensure thread safety/data synchronization

When multiple sub-threads access the same piece of data, the data may be modified at the same time due to non-synchronous access, so the data is not accurate and unsafe.

Real-life cases

If a bank account can exist more than one bank card, three people go to different business points at the same time to save money, assuming that the original account has 100 yuan, now three people each save 100 yuan, our final result should be 100 + 3 * 100 = 400 Yuan. However, as multiple people access the data at the same time, there may be three people in the meantime to get the original account number 100, and then add the remaining 100 to modify the data, may finally be 200, 300 or 400. In this case, a lock is required, and when one is operating, the original account is locked and cannot be manipulated by another person.

Case (non-thread-safe) code implementation:

1, program entry, start three threads in the background loop to perform tasks, add 100 tasks to the queue:

/** * Program Entry */public void Start () {    //start three threads for    (int i = 0; i < 3; i++) {        new MyTask (Blockingqueue). Start ( );    }     Add 100 tasks to allow three threads to execute for    (int i = 0; i < i++) {        Tasker Tasker = Tasker.getinstance ();        Blockingqueue.add (tasker);    }}

 2 . Let's take a look at MyTask how this thread is going and how it performs Tasker this task.

public class MyTask extends Thread {     ...     @Override public    Void Run () {when        (true) {            try {                Tasker person = Blockingqueue.take ();                Person.change ();            } catch (Interruptedexception e) {                e.printstacktrace ();}}}}    

 

Analysis of the above code, is to wait for the Loop convenience queue, each get a Tasker time to call void change() the method to Tasker perform the task in the child thread.

3, We are looking at Tasker how the object executes, singleton mode of the object, is repeatedly added to the queue to execute the void change() method:

public class Tasker implements Serializable, comparable<tasker> {     private static Integer value = 0;     public void Change () {        value++;        System.out.println (value);    }    ...}

Let's analyze the above code, void change() each call, the value of the property value has been added 1, theoretically it should be 012345678910... Such data are printed out, the worst case is also 1 3 4 6 5 2 8 7 9 10 12 11 ... It's a bit of a mess, but let's run it up and see:

We found out why there are 3 4 3 3 This duplication of data appears? Well, this is the beginning of the article said that the number of threads to get the value fields are 2, and then each +1 after the printout of the results are 3, if applied to our banking system, then this is not a pit father, so we in the post-development of multi-threaded use of the lock.

Multithreading ensures thread safety and data synchronization of data

The inevitable use of multi-threaded development in the lock, a lock of code is executed by a thread before the thread to get the permission to execute this code, in Java is to get a synchronization object lock (an object only a lock), if this time the synchronization of the object's lock is taken away by other threads, This thread is only waiting (threads are blocked in the lock pool wait queue). After the permission (lock), he began to execute the synchronization code, the thread executes the synchronization code immediately after the lock back to the synchronization object, the other in the lock pool waiting for a thread to get the lock to execute the synchronization code. This ensures that only one thread is executing at the same time in the synchronization code. There are two types of locks commonly used in Java, synchronized and lock.
Lock features: Each object has only one lock, whether it is synchronized or lock they can only lock a specific object, that is, the object must be unique, to be locked, not used by multiple threads.

Features of synchronized

A synchronous lock, which automatically releases the lock when it locks the method or block of code, but does not perform as well if the resource it locks is being fiercely competitive by the thread.

1. Let's look at the following code:

Add 100 tasks to allow three threads to execute for (int i = 0; i < i++) {    Tasker Tasker = new Tasker ();    Blockingqueue.add (tasker);}

 This code is the first paragraph of the article, but Tasker.getInstance() instead new Tasker(); , we now give Tadker the void change() method plus synchronized Lock:

/** * perform task; synchronized lock method. */public synchronized Void Change () {    value++;    System.out.println (value);}

  After we executed it again, how did Emma still have repeated digital prints, not locked up? But careful readers notice that we add Tasker to the queue every time, so that each new Tasker(); add to the task is a new object, so each object has its own lock, a total of 3 threads, each thread holds the current task out of the object's lock, which must not produce a synchronous effect. In other words, if the value is to be synchronized, then the object locks held by these threads should be shared and unique! This verifies the characteristics of the above-mentioned lock. Then the correct code should be:

Tasker Tasker = new Tasker (); for (int i = 0; i <; i++) {    blockingqueue.add (Tasker);}

  or provide a singleton pattern for this task:

for (int i = 0; i < i++) {    Tasker Tasker = Tasker.getinstance ();    Blockingqueue.add (tasker);}

 So that the object is unique, then public synchronized void change() the lock is unique.

2 . Do we have to write a singleton pattern for each task, and do we change the properties of the object before changing it? So we have a solution for using synchronized: Put a static object in the code block that executes the task, and then lock with synchronized. We know that static objects do not change with the object but always exist in memory, so:

private static Object object = new Object (); public void Change () {    synchronized (object) {        value++;        System.out.println (value);}    }

  This guarantees the uniqueness of the lock object, regardless of whether we use new Tasker(); or Tasker.getInstance(); not to be affected.
We know that for a synchronous static method, the object lock is the class instance of the classes in which the static drop is located, because in the JVM all the loaded classes have a unique class object, specifically in this case, the only Tasker.class object. No matter how many instances of the class we have created, its class instance is still one. So the code above can also be changed to:

public void Change () {    synchronized (tasker.class) {        value++;        System.out.println (value);}    }

 According to the above experience, our Tasker.getInstance(); method should be as follows:

private static Tasker Tasker; public static Tasker getinstance () {    synchronized (tasker.class) {        if (Tasker = = null)            Tasker = new Tasker (); C5/>return tasker;    }}

 3 . The synchronized code block automatically releases the lock when it encounters an exception. We mentioned above that the synchronized automatically releases the lock after encountering an exception, so if we cannot guarantee that the code block will be an exception (when resources are not tense) is possible to use synchronized, we simulate:

public void Change () {    synchronized (object) {        value++;        System.out.println (value);    }    if (value = =)        throw new RuntimeException ("");}

 The above code should be clear, but the value increases to 50, the thread will be an exception, according to our inference, the execution of 50 of this thread crashes, but the other two threads should still be normal execution, let us test:

We saw that before the three numbers were printed together, and then two threads were printed together, apparently a thread crashed and two threads were executing, indicating object that the lock was released.

Lock

Since we mentioned the synchronized inability to interrupt a thread waiting to get a lock, we couldn't get a lock by voting, and if we didn't want to wait, we couldn't get the lock. So the JSR 166 group took the time to develop a framework for us, java.util.concurrent.lock Lock which does not automatically release the lock when a locked method or block of code occurs, and it has the synchronized same concurrency and memory semantics, but adds some features like lock polling, timed lock waiting, and interruptible lock waiting. In addition, it provides better performance in the case of intense contention. (In other words, when many threads are trying to access a shared resource, the JVM can spend less time dispatching the thread and more of it to the execution thread.) )
What are the implementation classes for lock? We select in the code Lock and press Ctrl + T to show the following:

We see a read-out lock, ReadLock a write lock, WriteLock a re-entry lock ReenTrantLock , which we mainly say is the most reentrant lock used in multithreaded development ReenTrantLock .
Not much nonsense to say, in fact, the code is the same as above, we see how to achieve:

/** Lock module Case **/private static lock lock = new Reentrantlock (); public void Change () {Lock.lock (); {//code block    value++;    System.out.println (value);} Lock.unlock ();}

 We see the use is quite simple, and extensibility is better. But what we mentioned above is that if we had an exception here:

{//code block    value++;    System.out.println (value);}

  Tested, sure enough to be locked up, all the threads can not get execute permission, so here also gives a solution, haha maybe you have thought of, is our try {} finally {} :

public void Change () {    lock.lock ();    try {        value++;        System.out.println (value);        if (value = =)            throw new RuntimeException ("");    } finally {        lock.unlock ();    }}

  

We see that we add one and the same exception in the above code synchronized , we again test found that there is no exception at all, ah haha, this is, this is ReentrantLock to see the friend you will use it?

Nohttp Source and demo hosted at GitHub welcome Star: Https://github.com/yanzhenjie/NoHttp

Very instructive for beginners ...

Synchronized and Lock of thread safety and data synchronization

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.