Detailed safety java concurrency

Thread class security definitions 

If you use this class multi-threaded, multi-threaded, but how to use and schedule the class, which always shows the correct behavior, this class is thread-safe.

Thread-safe performance class as follows:

  • Atomic operation
  • Visibility memory

Do not do proper synchronization, when the shared state between multiple threads, the thread will appear unsafe.

How to achieve thread-safe class?

Stack closed

All variables are declared inside the method, these variables are in the stack closed.

no status

No class member variables of the class, called stateless

Let immutable class

Let immutable state, in two ways:

1, plus the final keyword for a class, all member variables should be private, the same as long as possible, all member variables should be added to the final keyword, but with final, should pay attention if the member variable is a when an object, the object corresponding to the class should not be changed, in order to ensure that the entire class is immutable.

2, did not provide any alternative modification of the local member variables, member variables are not at the same time as the return value

volatile

Ensure the visibility of the class, the most suitable for a write thread, multiple threads read the scene,

Locking and CAS

synchronized、reentrantLock和cas

Safe release

Class member variables held, in particular, is a reference to the object, if the member object is not thread safe, get advertised through other methods, will cause the data held by members of the object itself incorrect modification in a multi-threaded, so cause a problem entire class thread safe.

TheadLocal

Deadlock

Deadlock: refers to two or more processes in the implementation process, due to the competition for resources or A blocking phenomenon caused due communicate with each other, without external force, they will not be able to promote it. At this time, say the system is in deadlock state or system to produce a deadlock.

Resources must be more than one, but less than the number of threads equal competition, only one resource, will only produce intense competition.

The root cause of the deadlock: the order to acquire the lock leads to inconsistency.

Solution: assure an orderly locked

Examples of simple deadlock

public  class DeadLockDemo {
     public  static  void main (String [] args) {
         // creates two threads 
        DeadLockThread DT1 = new new DeadLockThread ( to false ); 
        DeadLockThread DT2 = new new DeadLockThread ( to true );
         // start threads 
        new new the Thread (DT1) .start ();
         new new the Thread (DT2) .start (); 
    } 
} 

class DeadLockThread the implements the Runnable {
     // flag variable 
    Private  Boolean In flag; 

    public DeadLockThread(boolean flag) {
        super();
        this.flag = flag;
    }

    public void run() {
        // dt1线程执行该方法
        if (flag) {
            synchronized (ThreadLock.locka) {
         Thread.sleep(100); System.out.println(
"if locka!"); synchronized (ThreadLock.lockb) { System.out.println("if lockb!"); } } } // dt2线程执行该方法 else { synchronized (ThreadLock.lockb) {
Thread.sleep(100); System.out.println(
"else lockb!"); synchronized (ThreadLock.locka) { System.out.println("else locka!"); } } } } } class ThreadLock { static Object locka = new Object(); static Object lockb = new Object(); }

operation result:

if locka!
else lockb!

To put it plainly, a thread is waiting to acquire possession of the two thread-locking thread two threads are waiting to acquire possession of a lock, fight each other! ! !

This is the most simple, nothing to say. . .

Dynamic Deadlock

Dynamic sequence deadlock in achieving a lock in a certain order, but because of problems external calls, resulting in no guarantee that locking sequence generated.

solve:

1, the internal sorting, to ensure the locking of the sequential

2, by trying to get a lock, you can.

Account categories:

Package com.ty.thread.account; 

Import java.util.concurrent.locks.Lock;
 Import java.util.concurrent.locks.ReentrantLock; 

/ ** 
 * Class Description: user account entity class 
 * / 
public  class the UserAccount { 

    / / Private int ID; 
    Private  Final String name; // account name 
    Private  int Money; // account balance
 public the UserAccount (String name, int AMOUNT) {
         the this .name = name;
         the this .money = AMOUNT; 
    } 

    public String getName () {
        return name;
    }

    public int getAmount() {
        return money;
    }

    @Override
    public String toString() {
        return "UserAccount{" +
                "name='" + name + '\'' +
                ", money=" + money +
                '}';
    }

    //转入资金
    public void addMoney(int amount){
        money = money + amount;
    }

    //转出资金
    public void flyMoney(int amount){
        money = money - amount;
    }
}

Transfer Interface:

Package com.ty.thread.transfer; 

Import com.ty.thread.account.UserAccount; 

/ ** 
 * Class Description: Bank transfer action interface 
 * / 
public  interface iTransfer {
     / ** 
     * 
     * @param from the transfer account 
     * @ param to transfer account 
     * @param aMOUNT transfer amount 
     * @throws InterruptedException
      * / 
    void Transfer (from the UserAccount, the UserAccount to, int aMOUNT) throws InterruptedException; 
}

Transfer thread class:

Package com.ty.thread.worker; 

Import com.ty.thread.account.UserAccount;
 Import com.ty.thread.transfer.ITransfer;
 / ** 
 * transfer operation executed thread 
 * / 
public  class TransferThread the extends the Thread { 

    Private String name; // thread name 
    Private the UserAccount from; 
     Private the UserAccount to; 
     Private  int AMOUNT;
     Private iTransfer Transfer; // actual transfer of the action 

    public TransferThread (String name from the UserAccount,, the UserAccount to,
                           int amount, ITransfer transfer) {
        this.name = name;
        this.from = from;
        this.to = to;
        this.amount = amount;
        this.transfer = transfer;
    }


    public void run(){
        Thread.currentThread().setName(name);
        try {
            transfer.transfer(from,to,amount);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

The following will be divided into several transfers scene, one by one to illustrate:

1, unsafe locking strategy

TrasnferAccount

package com.ty.thread.transfer.impl;

import com.ty.thread.account.UserAccount;
import com.ty.thread.transfer.ITransfer;

/**
 *类说明:不安全的转账动作的实现
 */
public class TrasnferAccount implements ITransfer {

    @Override
    public void transfer(UserAccount from, UserAccount to, int amount) 
            throws InterruptedException {
        synchronized (from){//先锁转出
            System.out.println(Thread.currentThread().getName() + " get"+from.getName());
            Thread.sleep(100);
            synchronized (to){//再锁转入
                System.out.println(Thread.currentThread().getName() + " get"+to.getName());
                from.flyMoney(amount);
                to.addMoney(amount);
            }
        }
    }
}

Run the main categories:

/ ** 
 * Class Description: Analog payment company operation transfers 
 * / 
public  class PayCompany { 

    public  static  void main (String [] args) { 
        the UserAccount zhangsan = new new the UserAccount ( "zhangsan", 20000 ); 
        the UserAccount Lisi = new new the UserAccount ( " Lisi ", 20000 ); 
        iTransfer Transfer = new new TrasnferAccount (); 
        TransferThread zhangsanToLisi = new new TransferThread (" zhangsanToLisi ", zhangsan, Lisi, 2000 , Transfer); 
        TransferThread lisiToZhangsan = new new TransferThread("lisiToZhangsan",lisi,zhangsan,4000,transfer);
        zhangsanToLisi.start();
        lisiToZhangsan.start();

    }
}

operation result:

 

Will find that this has been stuck in, there was a deadlock.

The reason : the above start two threads, each thread is actually different from, for zhangsanToLisi thread, it is from zhangsan, to be lisi, but for lisiToZhangsan thread, it is the opposite, so two threads start , it will produce a deadlock situation.

2, but difficult to understand the security lock strategy

Package com.ty.thread.transfer.impl; 

Import com.ty.thread.account.UserAccount;
 Import com.ty.thread.transfer.ITransfer; 

/ ** 
 * Class Description: no secure transfer deadlock 
 * / 
public  class SafeOperate the implements iTransfer {
     Private  static object tieLock = new new object (); // overtime lock 

    @Override 
    public  void Transfer (from the UserAccount, the UserAccount to, int AMOUNT)
             throws InterruptedException { 
        // the hash value comparison by the object, so that it will not appear from to confusion 
        int fromHash = System.identityHashCode(from);
        int toHash = System.identityHashCode(to);
        //先锁hash小的那个
        if(fromHash<toHash) {
            synchronized (from){
                System.out.println(Thread.currentThread().getName()
                        +" get"+from.getName());
                Thread.sleep(100);
                synchronized (to){
                    System.out.println(Thread.currentThread().getName()
                            +" get"+to.getName());
                    from.flyMoney(amount);
                    to.addMoney(amount);
                }
            }            
        }else if(toHash<fromHash) {
            synchronized (to){
                System.out.println(Thread.currentThread().getName()
                        +" get"+to.getName());
                Thread.sleep(100);
                synchronized (from){
                    System.out.println(Thread.currentThread().getName()
                            +" get"+from.getName());
                    from.flyMoney(amount);
                    to.addMoney(amount);
                }
            }            
        }else {//解决hash冲突的方法
            synchronized (tieLock) {
                synchronized (from) {
                    synchronized (to) {
                        from.flyMoney(amount);
                        to.addMoney(amount);                        
                    }
                }
            }
        }
        
    }
}

This is way too much trouble, but it is thread-safe.

3, well-understood security policy

First class modify accounts, increased lock lock

Package com.ty.thread.account; 

Import java.util.concurrent.locks.Lock;
 Import java.util.concurrent.locks.ReentrantLock; 

/ ** 
 * Class Description: user account entity class 
 * / 
public  class the UserAccount { 

    / / Private int ID; 
    Private  Final String name; // account name 
    Private  int Money; // account balance 

    // display lock 
    Private  Final lock lock = new new of ReentrantLock (); 

    public lock a GETLOCK () {
         return lock; 
    } 

    public the UserAccount (String name,int amount) {
        this.name = name;
        this.money = amount;
    }

    public String getName() {
        return name;
    }

    public int getAmount() {
        return money;
    }

    @Override
    public String toString() {
        return "UserAccount{" +
                "name='" + name + '\'' +
                ", money=" + money +
                '}';
    }

    //转入资金
    public void addMoney(int amount){
        money = money + amount;
    }

    //转出资金
    public void flyMoney(int amount){
        money = money - amount;
    }
}
Package com.ty.thread.transfer.impl; 

Import java.util.Random; 

Import com.ty.thread.account.UserAccount;
 Import com.ty.thread.transfer.ITransfer; 

/ ** 
 * Class Description: no the second method of transfer security deadlock, get lock attempt 
 * / 
public  class SafeOperateToo the implements iTransfer { 
    
    @Override 
    public  void Transfer (from the UserAccount, the UserAccount to, int AMOUNT)
             throws InterruptedException { 
        the Random R & lt = new new the Random ();
         the while ( to true ) {
             IF(from.getLock().tryLock()) {
                try {
                    System.out.println(Thread.currentThread().getName()+" get "+from.getName());
                    if(to.getLock().tryLock()) {
                        try {
                            System.out.println(Thread.currentThread().getName()+" get "+to.getName());                            
                            //两把锁都拿到了
                            from.flyMoney(amount);
                            to.addMoney(amount);
                            break;
                        }finally {
                            to.getLock () UNLOCK ();. 
                        } 
                    } 
                } the finally { 
                    from.getLock () UNLOCK ();. 
                } 
            } 
            // Sleep plus place for a reason, because the lock code logic is two account object, if the thread a got a lock accounts, two thread got a lock B accounts, which is a thread to acquire the lock B fails, a lock release, thread two a failure to obtain, and release the B, comity. . . This competition by reducing the probability of sleep! 
            Thread.sleep (r.nextInt ( 10 )); 
        } 
    } 
}

Run method:

    public static void main(String[] args) {
        UserAccount zhangsan = new UserAccount("zhangsan",20000);
        UserAccount lisi = new UserAccount("lisi",20000);
        ITransfer transfer = new SafeOperateToo();
        TransferThread zhangsanToLisi = new TransferThread("zhangsanToLisi",zhangsan,lisi,2000,transfer);
        TransferThread lisiToZhangsan = new TransferThread("lisiToZhangsan",lisi,zhangsan,4000,transfer);
        zhangsanToLisi.start();
        lisiToZhangsan.start();
    }

operation result:

 

Description: The spin + ReentrantLock achieve thread safety.

Guess you like

Origin www.cnblogs.com/alimayun/p/12169114.html