`
Mr_mai
  • 浏览: 7531 次
  • 性别: Icon_minigender_2
  • 来自: 温州
最近访客 更多访客>>
社区版块
存档分类
最新评论

线程同步

阅读更多

 

 

1、线程是什么,线程是一份独立运行的程序,有自己专用的运行空间,有可能和其他线程共享一些资源,比如,内存,文件,数据库等。

2、线程同步的概念。当多个线程共同占用一个资源的时候,这时候就要用到线程同步这个概念。线程同步的“同”字可能会让很多人误解,往往会被理解成几个线程一起进行,其实“同”的真正解释是指协同、协助、互相配合。比如说厕所,一个厕所同时只能给一个人占用,当一个人进去的时候,其他人就要在外面等待,里面的人出来以后外面的人才能够进去使用。   再来说说为什么需要线程同步, 最好的例子就是银行的账户,假设你在银行开了一个账户,Account,同时拿到一本存折还有一张银行卡,假设你的银行卡里面有3000大洋。有一天,你和你的女朋友分别拿着银行卡和存折同时在ATM取款机还有银行柜台取钱。两种方式两个线程,共享Account这个账户,假使你用银行卡取钱的时候线程1在操作Account,取出3000,但是在ATM吐出钱而Account还没有扣钱的时候,线程2又启动了,因为线程2并不知道线程1已经取了3000,你的女朋友在柜台又取了3000,这样银行岂不是亏了3000?

 

 public getCash(Account ac, String name, int cash) { 
 this.ac = ac;
 this.cash = cash;
 this.name = name;
 }


 public void run() {
 // synchronized (ac) { 
 int count = ac.getCash(cash);
 System.out.println(name + "取了" + count);
   // } 
} 


public Account(int num){
      this.total=num;
 } 


public int getCash(int cash){
 if(cash>total){
    return -1;
    } 
  else{
     disSave(cash);
      return cash; 
   }
 }

 

public static void main(String arg[]) throws Exception{
 Account ac=new Account(3000); 
 getCash thread1=new getCash(ac,"ATM",3000);
 getCash thread2=new getCash(ac,"柜台",3000); 
 thread1.start(); 
 thread2.start();
 Thread.sleep(5000);
 System.out.println(ac);
 }

 

  运行结果:柜台取了3000 ATM取了3000 总共还有金额:-3000  

 

3、然后我们看一下怎么样才能实现线程的同步。  

 (1)关键字synchronized,我们可以在我们需要共享的资源上加锁,这样就可以保证该对象只能被一个用户使用。     

 a、synchronized 锁定一个独立的代码块  

 

    public void run(){

  while(true){

  synchronized(lock){

  ...... //共享资源

  }

 }

}

     上诉代码可以理解为每当执行while里面代码时,共享资源就会被锁定,执行完以后释放锁。  

 

    b、synchronized 关键字还可以修饰一个函数   

         //取钱,够的话扣除然后返回要扣除的钱的总数不够的话返回-1

    public synchronized int getCash(int cash){ 

       if(cash>total){

            return -1;

         } else{

        disSave(cash);

        return cash; 

     }

   }

 

   同理当使用上面的函数的时候这个函数就会被锁定。

 

PS:   需要注意的就是synchronized(Lock)里面的Lock必须是公共锁。假如我在Thread1中创建了一个锁lock1,在Thread2也创建了一个锁lock2,那么“上锁”也就没意义了。就好像一个公共教室,我进门锁了门,但是另一个人开了后门从后门进,我锁没锁前门也就没有意义了。   

2、看下述代码

      private byte[] lock = new byte[0];

 

      public void methodA() {

         synchronized(lock) {

            …

           }

        }

       使用这种方式生成锁可以称作大神级别的作品,后来查找了下原因,因为生成零长度的byte[]对象只需3条操作码,而Object lock= new Object()则需要7行操作码,所以生成byte[0]是最经济的一种方式。

 

(2)使用同步锁Lock。Java中有一个包java.util.concurrrent.locks.Lock接口。   具体的使用方法是:

  //先生成一个公共锁。   

       Java.util.concurrent.Lock lock=new java.util.concurrrent.locks.Lock.ReentrantLock();

  lock.lock();

       //开始上锁

  try{

      doSomeThing. //共享资源

  }

  finally{

  lock.unlock();

  }

 

       synchronized和lock相同与不同: 凡是synchronized能实现的效果lock都是可以实现的,不同的是,lock锁定后执行的内容必须放在try里面,而解锁的unlock必须放finally里面。 当然,同步是要很大的系统开销作为代价的,有时候可能会导致死锁,因此要避免无谓的同步。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics