Concurrency model-shared memory model (thread and lock) example, model example
The shared memory model, as its name implies, implements a concurrency model through shared memory, when multiple threads use shared resources in concurrent execution, errors such as dirty Data Reading and invalid data may occur if they do not agree on the shared resources or perform special processing; to solve these problems caused by shared resources, Java introduces synchronization, locks, atomic types, and other operations for processing shared resources;
In this article, we will use several demos to introduce Java's synchronized, lock, and atomic related classes. Java's shared memory concurrency model is also reflected in synchronized and lock) and so on;
Synchronization:
In the Demo, two threads are enabled to call a counter. At this time, the counter becomes the shared resource of two threads, and both threads compete for shared resources, when the actual state conditions are not processed, the data obtained may be abnormal or incorrect;
1 /** 2 * Created by linx on 2015-05-12. 3 */ 4 public class Counter { 6 private int count = 0; 8 public void increment() { 9 ++count;10 }12 public int getCount() {13 return count;14 }15 }16 /**17 * Created by linx on 2015-05-12.18 */19 public class CountThread extends Thread {20 21 private Counter counter;22 public CountThread(Counter counter) {23 this.counter = counter;24 }25 @Override26 public void run() {27 for (int i = 0; i < 5000; i++) {28 counter.increment();29 }30 }31 }32 /**33 * Created by linx on 2015-05-12.34 */35 public class CountMain {36 37 public static void main(String[] args) throws InterruptedException {38 39 Counter counter = new Counter();40 AtomicCounter atomicCounter=new AtomicCounter();41 CountThread t1 = new CountThread(counter);42 CountThread t2 = new CountThread(counter);43 t1.start();44 t2.start(); 45 t1.join();46 t2.join();47 System.out.println(counter.getCount());48 } 49 }
Almost every time I run this code, the results are different. The results are as follows:
The results are unpredictable because there are actual conditions;
The solution to the final state condition is to lock and synchronize the resources that compete for the lock. in java, you can use synchronized or lock;
Now let's modify the counter code:
public synchronized void increment() { ++count;}
Here we only add the synchronized keyword in the increment method declaration. At this time, we are executing the program. Now every time we get the result, it will be 10000,
Because we have solved the final state conditions, a thread will enter the increment method for execution at the same time, so what we get at this time is the correct result;
Lock
Here we just replace synchronized in the Demo with the Lock object, and the results are the same;
/** * Created by linx on 2015-05-12. */public class Counter { private int count = 0; Lock lock=new ReentrantLock(); public void increment() { lock.lock(); try { ++count; }finally { lock.unlock(); } } public int getCount() { return count; }}
Here we show that the explicit ReentrantLock object is used to lock the code block in the increment method. Other synchronized also locks the method, but it uses the built-in lock of the object;
Atomic type
The above Demo only causes problems when there is no synchronization or lock, because ++ count is not Atomic. It is actually read-modify-write, as long as the increment can be ensured to be an atomic method, this is not a problem. Now let's change count to the atomic type;
/** * Created by linx on 2015-05-12. */public class AtomicCounter { private AtomicInteger count=new AtomicInteger(); public void increment() { count.incrementAndGet(); } public AtomicInteger getCount() { return count; }}
This counter class is not subject to any synchronization or lock, because the increment method is atomic.
Advantages and disadvantages
Advantage: The Memory sharing model or the thread and lock model is widely used. This model also exists in almost every operating system, so it is also a very common model.
Disadvantages: there are some problems with the thread and lock model: the system does not directly support concurrency, and cannot or is difficult to implement distributed shared memory. It is difficult to test the thread and lock model, in multi-thread programming, problems occur inadvertently many times, but we don't know yet. When a Bug suddenly occurs, it is often difficult for us to reproduce the Bug, the shared memory model cannot be used to establish a mathematical model. There is a lot of uncertainty in it. Uncertainty indicates that the problem may be hidden, and the human thinking is just a single thread;
In addition, the creation of threads also consumes a lot of resources, and the competition in actual state conditions and locks among multiple threads will also affect the performance if the processing is poor;
First Article address: Solinx
Http://www.solinx.co/archives/190