java线程同步

来源:互联网 发布:网络机顶盒 会员 编辑:程序博客网 时间:2024/06/03 17:32

转自:战国剑的博客,网址:http://blog.csdn.net/yangzhaomuma/article/details/51236976


其中,图中标红的方法已经过时。


(1)join方法,主要作用是在该线程中的run方法结束后,才能向下执行。如:


package threadTest;

public class ThreadJoin {  
      
    
    public static void main(String[] args) {  
 
        Thread thread= new Thread(new Runnable() {  
              
            @Override  
            public void run() {  
                System.err.println("线程"+Thread.currentThread().getId()+" 打印信息");  
            }  
        });  
        thread.start();  
          
        try {  
            thread.join();  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        
        System.err.println("主线程打印信息");  
          
    }  
 

//如果有  thread.join();  ,则会先运行run方法的    System.err.println("线程"+Thread.currentThread().getId()+" 打印信息");  ,之后运行System.err.println("主线程打印信息"); 

,即

线程9 打印信息
主线程打印信息


否则:

主线程打印信息
线程9 打印信息


(2)Synchronized(同步锁)

张三在银行账户存有100元,经过多次的取200,存200后,账户还有多少钱?

package threadTest;

import java.sql.Time;  
import java.util.concurrent.TimeUnit;  
 
public class Account {  
 
    private String name;  
    private float amt;  
    public Account(String name,float amt) {  
        this.name=name;  
        this.amt=amt;  
    }  
    public  void  increaseAmt(float increaseAmt){  
        try {  
            TimeUnit.SECONDS.sleep(1);  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        amt+=increaseAmt;  
        System.out.println("增加:"+amt);
    }  
      
    public  void decreaseAmt(float decreaseAmt){  
        try {  
            TimeUnit.SECONDS.sleep(1);  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        amt-=decreaseAmt;  
        System.out.println("减少:"+amt);
    }  
      
    public void printMsg(){  
        System.out.println(name+"账户现有金额为:"+amt);  
    }  
    
    public  static void main(String[] args){
        final int NUM=100;  
        Thread[] threads=new Thread[NUM];  
        final Account account=new Account("zhou",200);
        for(int i=0;i<NUM;i++){  
            if(threads[i]==null){  
                threads[i]=new Thread(new Runnable() {  
                      
                    @Override  
                    public void run() {  
                        account.increaseAmt(100f);  
                        account.decreaseAmt(100f);  
                    }  
                });  
                threads[i].start();  
            }  
        }  
        for(int i=0;i<NUM;i++){  
            try {  
                threads[i].join();  
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
          
        account.printMsg();  
    }
    
}
分别多次运行,出现不同的结果。

增加:700.0
增加:700.0
增加:1300.0
增加:1300.0
增加:3900.0
....
减少:5500.0
减少:5800.0
zhou账户现有金额为:-100.0


不符合实际


加锁方法:

a.动态方法加锁

public synchronized void doSomething(){} 

b代码块的修饰

  1. public  void  increaseAmt(float increaseAmt){  
  2.           
  3.         try {  
  4.             TimeUnit.SECONDS.sleep(1);  
  5.         } catch (InterruptedException e) {  
  6.             // TODO Auto-generated catch block  
  7.             e.printStackTrace();  
  8.         }  
  9.         synchronized (this) {  
  10.             System.out.println(this);  
  11.             amt+=increaseAmt;  
  12.         }  
  13.     } 
c静态方法修饰

  1. public synchronized static  void  increaseAmt(float increaseAmt){  
  2.         try {  
  3.             TimeUnit.SECONDS.sleep(1);  
  4.         } catch (InterruptedException e) {  
  5.             // TODO Auto-generated catch block  
  6.             e.printStackTrace();  
  7.         }  
  8.         amt+=increaseAmt;  
  9.     } 
类的修饰

  1. synchronized (AccountSynchronizedClass.class) {  
  2.         amt-=decreaseAmt;  
  3.     }

正确的形式:

package threadTest;

import java.util.concurrent.TimeUnit;  
/**  
 * Synchronized 代码块  
 * @author 战国  
 *  
 */  
public class AccountSynchronizedBlock {  
 
    private String name;  
    private float amt;  
    public AccountSynchronizedBlock(String name,float amt) {  
        this.name=name;  
        this.amt=amt;  
    }  
 
    public  void  increaseAmt(float increaseAmt){  
          
        try {  
            TimeUnit.SECONDS.sleep(1);  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        synchronized (this) {  
            System.out.println(this);  
            amt+=increaseAmt;  
        }  
    }  
      
    public  void decreaseAmt(float decreaseAmt){  
        try {  
            TimeUnit.SECONDS.sleep(1);  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        synchronized (this) {  
            System.out.println(this);  
            amt-=decreaseAmt;  
        }  
          
    }  
      
    public void printMsg(){  
        System.out.println(name+"账户现有金额为:"+amt);  
    }  
    
    
    public static void main(String[] args){
        
        //多线程synchronized修饰代码块 ,每次计算的值都一样  
        
        final AccountSynchronizedBlock account=new AccountSynchronizedBlock("张三", 100.0f);  
        final int NUM=50;  
          
        Thread[] threads=new Thread[NUM];  
        for(int i=0;i<NUM;i++){  
            if(threads[i]==null){  
                threads[i]=new Thread(new Runnable() {  
                      
                    @Override  
                    public void run() {  
                        account.increaseAmt(100f);  
                        account.decreaseAmt(100f);  
                    }  
                });  
                threads[i].start();  
            }  
        }  
          
        for(int i=0;i<NUM;i++){  
            try {  
                threads[i].join();  
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
        account.printMsg();  
        
    }
    



(3)lock

2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;

3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

Lock提供多种方式获取锁,有Lock、ReadWriteLock接口,以及实现这两个接口的ReentrantLock类、ReentrantReadWriteLock类。




package threadTest;

import java.util.ArrayList;  
import java.util.List;  
import java.util.concurrent.locks.Lock;  
import java.util.concurrent.locks.ReadWriteLock;  
import java.util.concurrent.locks.ReentrantLock;  
import java.util.concurrent.locks.ReentrantReadWriteLock;  
 
public class LockImp {  
 
      
    private Lock lock=new ReentrantLock();  
    private ReadWriteLock rwLock=new ReentrantReadWriteLock();  
      
    private List<Integer> list=new ArrayList<Integer>();  
      
    public void doReentrantLock(Thread thread){  
        lock.lock();  
        System.out.println(thread.getName()+"获取锁");  
        try {  
              for(int i=0;i<10;i++){  
                    list.add(i);  
                }  
        } catch (Exception e) {  
              
        }finally{  
            lock.unlock();  
            System.out.println(thread.getName()+"释放锁");  
        }          
    }
    public void doReentrantReadLock(Thread thread){  
        rwLock.readLock().lock();  
        System.out.println(thread.getName()+"获取读锁");  
        try {  
            for(int i=0;i<10;i++){  
                list.add(i);  
            }
            System.out.println(list);
        } catch (Exception e) {  
              
        }finally{  
            rwLock.readLock().unlock();  
            System.out.println(thread.getName()+"释放读锁");  
        }  
          
    }  
    public void doReentrantWriteLock(Thread thread){  
        rwLock.writeLock().lock();  
        System.out.println(thread.getName()+"获取写锁");  
        try {  
            for(int i=0;i<10;i++){  
                list.add(i);  
            }  
        } catch (Exception e) {  
              
        }finally{  
            rwLock.writeLock().unlock();  
            System.out.println(thread.getName()+"释放写锁");  
        }  
          
    }  
      
    /**  
     * @param args  
     */  
    public static void main(String[] args) {  
 
        final LockImp lockImp=new LockImp();  
          
        final Thread thread1=new Thread();  
        final Thread thread2=new Thread();  
        final Thread thread3=new Thread();  
          
        new Thread(new Runnable() {  
              
            @Override  
            public void run() {  
                System.out.println("thread1 run");
                lockImp.doReentrantLock(thread1);  
            }  
        }).start();  
          
        new Thread(new Runnable() {  
                      
                    @Override  
                    public void run() {  
                        System.out.println("thread2 run");
                        lockImp.doReentrantLock(thread2);  
                    }  
                }).start();  
          
        new Thread(new Runnable() {  
              
            @Override  
            public void run() {  
                System.out.println("thread3 run");
                lockImp.doReentrantLock(thread3);  
            }  
        }).start();  
      
          
        lockImp.doReentrantReadLock(thread1);  
        
        lockImp.doReentrantReadLock(thread2);  
        lockImp.doReentrantReadLock(thread3);  
          
        lockImp.doReentrantWriteLock(thread1);  
        lockImp.doReentrantWriteLock(thread2);  
        lockImp.doReentrantWriteLock(thread3);  
    }  
 



输出:

thread1 run
Thread-0获取锁
thread2 run
Thread-0释放锁
Thread-1获取锁
Thread-1释放锁
Thread-0获取读锁
thread3 run
Thread-2获取锁
Thread-2释放锁
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Thread-0释放读锁
Thread-1获取读锁
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Thread-1释放读锁
Thread-2获取读锁
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Thread-2释放读锁
Thread-0获取写锁
Thread-0释放写锁
Thread-1获取写锁
Thread-1释放写锁
Thread-2获取写锁
Thread-2释放写锁


如果为单个锁和线程,则输出:

Thread-0获取读锁
thread1 run
Thread-0获取锁
Thread-0释放锁
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Thread-0释放读锁





原创粉丝点击