java multithreading (six) thread control class

1. multiple threads of control class

In order to ensure the three characteristics of a multi-threaded, Java introduces many thread control mechanism, here are several commonly used where:

l  ThreadLocal

l - Atom

l Lock class

l Volatile keyword

1.1. ThreadLocal

1.1.1 Role

ThreadLocal provides thread-local variables, each thread is the use of the same variable to maintain a copy of the variable.

When some data is thread scope and different threads have different copies of data when you can consider using ThreadLocal, such as database connections Connection, each request processing threads are needed, but do not affect each other, it is to use ThreadLocal achieve .

1.1.2. Examples

Two threads each transfer

Package Penalty for com.controller; 

/ ** 
 * @Auther: lanhaifeng 
 * @date: 2019/11/21 0021 10:09 
 * @Description: Thread local variables ThreadLocal 
 * @statement: 
 * / 
public  class ThreadLocaclDemo {
     // 1. create a bank Object: money, withdrawal, deposit 
    static  class Bank {
         Private the threadLocal <Integer> = threadLocal new new the threadLocal <Integer> () { 
            @Override 
            protected Integer the initialValue () {
                 return 0 ; 
            } 
        }; 

        public Integer GET () {
             returnThreadLocal.get (); 
        } 

        public  void SET (Integer Money) { 
            to ThreadLocal.set (ThreadLocal.get () + Money); 
        } 
    } 
    // 2. Create Object Transfer: withdraw money from a bank, transfer, save to account 
    static  class Transfer the implements the Runnable {
         Private Bank Bank; 

        public Transfer (Bank Bank) {
             the this .bank = Bank; 
        } 
        public  void RUN () {
             for ( int I = 0; I <10; I ++ ) { 
                bank.set ( 10 );
                System.out.println (Thread.currentThread () getName (). + "Account Balance:" + bank.get ()); 
            } 
        } 
    } 
    // 3. analog transfer using two objects in the main method 
    public  static  void main (String [] args) { 
        Bank Bank = new new Bank (); 
        Transfer Transfer = new new Transfer (Bank); 
        the Thread Thread1 = new new the Thread (Transfer, "customer. 1" ); 
        the Thread Thread2 = new new the Thread (Transfer, "client 2" ); 

        thread1.start (); 
        thread2.start (); 
    } 
}

Implementation of the results:

1.1.3 Analysis

l is defined in a ThreadLocalMap ThreadLocal class,

l Each Thread has a variable of type threadLocals ThreadLocalMap

Internal l threadLocals a Entry, Entry ThreadLocal object instance is the key, value is a copy of the shared variables

l ThreadLocal get method is to obtain a copy of the shared instance variables based on ThreadLocal objects

L ThreadLocal set method is to save a copy of the shared object instance variable The ThreadLocal

1.2. - Atom

Java.util.concurrent.atomic package the Java class which provides a number of atomic operations may be divided into the following four categories:

l atomic update basic types: AtomicInteger, AtomicBoolean, AtomicLong

l array atomic update: AtomicIntegerArray, AtomicLongArray

l atomic update references: AtomicReference, AtomicStampedReference etc.

l atomic update attributes: AtomicIntegerFieldUpdater, AtomicLongFieldUpdater

These classes provide atom is the basic problem of the type of operation leads to a non-atomic initiated in order to solve the case of multi-threaded.

1.2.1. Non-atomic operational problems demo

Non-atomic operations can cause the problem? I ++ Example below to demonstrate the problem of non-atomic operation.

i ++ is not atomic operation, but is composed of three operations:

tp1 = i;
tp2 = tp1+1;
i = tp2;

Therefore, the value of i is not a problem the single-threaded, multi-threaded but an error occurs, the following sample code multithreaded:

package com.multithread.thread;

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicClass {
static int n = 0;
public static void main(String[] args) throws InterruptedException {
int j = 0;
while(j<100){
n = 0;
            Thread t1 = new Thread(){
public void run(){
for(int i=0; i<1000; i++){
n++;
                    }
                }
            };
            Thread t2 = new Thread(){
public void run(){
for(int i=0; i<1000; i++){
n++;
                    }
                }
            };
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            System.out.println("n的最终值是:"+n);
            j++;
        }

    }
}

 

The results are as follows: find the final value n may not be 2000

 

 

1.2.2. - Atom solve the problem of non-atomic operations

The above code changes as follows:

package com.multithread.thread;

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicClass {
static AtomicInteger n;
public static void main(String[] args) throws InterruptedException {
int j = 0;
while(j<100){
n = new AtomicInteger(0);
            Thread t1 = new Thread(){
public void run(){
for(int i=0; i<1000; i++){
n.getAndIncrement();
                    }
                }
            };
            Thread t2 = new Thread(){
public void run(){
for(int i=0; i<1000; i++){
n.getAndIncrement();
                    }
                }
            };
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            System.out.println("n的最终值是:"+n);
            j++;
        }

    }
}

 

 

The results are as follows: the value of n is always 2000

 

1.2.3. CAS principle of atomic class analysis

 

 

1.2.4. CAS and solve the problem of ABA

1.2.4.1. ABA Analysis

The current value of the memory of a beginning is A, before being replaced by another thread B then changed to A, then when the current thread to access the discovery is A, then it is not considered to be accessed by other threads. In some scenarios this is an error risk. As shown below:

 

 

 

1.2.4.2. ABA Problem Solving

package com.multithread.thread;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

public class AtomicClass {
static AtomicStampedReference<Integer>n;
public static void main(String[] args) throws InterruptedException {
int j = 0;
while(j<100){
n = new AtomicStampedReference<Integer>(0,0);
            Thread t1 = new Thread(){
public void run(){
for(int i=0; i<1000; i++){
int stamp;
                        Integer reference;
do{
                            stamp = n.getStamp();
                            reference = n.getReference();
                        } while(!n.compareAndSet(reference, reference+1, stamp, stamp+1));
                    }
                }
            };
            Thread t2 = new Thread(){
public void run(){
for(int i=0; i<1000; i++){
int stamp;
                        Integer reference;
do{
                            stamp = n.getStamp();
                            reference = n.getReference();

                        } while(!n.compareAndSet(reference, reference+1, stamp, stamp+1));
                    }
                }
            };
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            System.out.println("n的最终值是:"+n.getReference());
            j++;
        }

    }
}

 

Implementation of the results is as follows: the results of 2000 also

 

Note: The AtomicStampedReference degrade performance, with caution.

 

1.3. Lock class

1.3.1. Lock the interface diagram

 

 

Lock and ReadWriteLock is the root interface of the two locks

Lock interface supports re-entry, fairness lock rule: implementation class ReentrantLock, ReadLock and WriteLock.
ReadWriteLock interface definition written by readers share exclusive lock, implementation class: ReentrantReadWriteLock.

 

1.3.2. Reentrant lock

Non-reentrant lock that it already has a lock thread requests will be blocked when.

Reentrant lock, i.e., the thread can enter the lock synchronization code blocks it already has.

publicclassReentrantLockTest {
 
public static void main(String[] args) throws InterruptedException {
 
        ReentrantLock lock = new ReentrantLock();
 
for  (int  i = 1 ; i <= 3; i++) {
lock.lock();
        }
 
for (int  i=1 ;i<=3;i++){
try {
 
            } finally {
lock.unlock();
            }
        }
    }
}

 

 

1.3.3. Read-Write Lock

Read-write locks, which can be read at the same time, when you can not read the writing; at the same time can not write, can not read the time to write.

Sample code:

package com.multithread.thread;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 *
读写操作类
 */
public class ReadWriteLockDemo {

private Map<String, Object>map = new HashMap<String, Object>();
//创建一个读写锁实例
private ReadWriteLock rw = new ReentrantReadWriteLock();
//创建一个读锁
Private Lock R & lt = RW .readLock ();
// Create a write lock
Private Lock W = RW .writeLock ();

/ **
     *
reads
     *
     * @param
Key
* @return
* /
public Object GET (String Key) {
R & lt .lock ();
        . the System OUT .println (. the Thread currentThread () .getName () + " a read operation is performed ......" );
the try {
            the Thread. SLEEP (3000);
        } the catch(InterruptedException e) {
            e.printStackTrace();
        }
try {
return map.get(key);
        } finally {
r.unlock();
            System.out.println(Thread.currentThread().getName() + "读操作执行完成......");
        }
    }

/**
     *
写操作
     *
     * @param
key
* @param value
*/
public void put(String key, Object value) {
try {
w.lock();
            . The System OUT .println (. The Thread currentThread () .getName () + " write operation is performed ......" );
the try {
                the Thread. SLEEP (3000);
            } the catch (InterruptedException E) {
                e.printStackTrace ( );
            }
Map .put (Key, value);
        } the finally {
W .unlock ();
            . the System OUT . .println (the Thread currentThread () .getName () + " write operations completed ......" ) ;
        }
    }

public static void main(String[] args) {
final ReadWriteLockDemo d = new ReadWriteLockDemo();
        d.put("key1", "value1");
new Thread(new Runnable() {
public void run() {
d.get("key1");
            }
        }).start();

new Thread(new Runnable() {
public void run() {
d.get("key1");
            }
        }).start();
new Thread(new Runnable() {
public void run() {
d.get("key1");
            }
        }).start();
    }

}

 

Implementation of the results is as follows: an exclusive write lock, can not be read during execution; read operations

 

1.4. Volatile keyword

1.4.1 Role

A shared variable (member variables of the class, the class of static member variables) after being declared volatile, then have the two semantics:

l ensure visibility when different threads to this variable operation, that is a thread modifies the value of a variable, this new value to other thread is immediately visible. (Note: do not guarantee atomicity)

l reorder instruction is prohibited. (Ensure the orderly rows of variable resides)

When the program is executed to read or write to a volatile variable, change in front of the entire operation certainly has, and the results are already visible on the back of the operation; operating behind it certainly has not been carried out;

During instruction optimization, we can not put it in the back of the implementation of the statement of the volatile variable access, nor can back into its volatile variables statement executed on the front.

 

 

1.4.2. Scenarios

Based volatile effect, the use of volatile following two conditions must be met:

l write operation is not dependent on the variable current value

The variable l is not included in the invariant with other variables

Common scenarios are as follows:

State the amount of labeled:

 

volatilebooleanflag = false;

 

while(!flag){

    doSomething();

}

 

publicvoidsetFlag() {

    flag = true;

}

 

 

volatilebooleaninited = false;

//线程1:

context = loadContext(); 

inited = true;           

 

//线程2:

while(!inited ){

sleep()

}

doSomethingwithconfig(context);

 

 

Double check:

classSingleton{

    privatevolatilestaticSingleton instance = null;

 

    privateSingleton() {

 

    }

 

    publicstaticSingleton getInstance() {

        if(instance==null) {

            synchronized(Singleton.class) {

                if(instance==null)

                    instance = newSingleton();

            }

        }

        returninstance;

    }

}

Guess you like

Origin www.cnblogs.com/zeussbook/p/11908993.html