你的分享就是我们的动力 ---﹥

关于多线程的几点总结

时间:2016-12-26 19:14来源:www.chengxuyuans.com 点击:
  1.  关于线程 synchronized关键字:
     不能用在变量和构造函数上
     放在方法上面,锁定的是对象,放在静态方法上锁定的是类
     不应该锁定常量,比如String等类型因为程序中这个对象难免还会用
     建议:
          A:尽量使用同步代码块而不是同步方法。因为同步方法是锁定对象,这样无关安全线程的方法也无法执行了,只锁定代码块,其他线程调用非同步方法的函数一样还可以执行。
      B:尽量锁定比较小的范围
      C:选择锁的问题,尽量定义一个私有对象来锁定。该对象不可共有,因为公有可以被修改,无法保证锁的唯一,外部修改之后就可以任意执行同步块里的内容,尽量不要对外提供这个对象set方法,原因同上
  2. 关于wait()
     该方法使当前线程等待,直到其锁的对象使用notify或者notifyAll
     该方法必须拥有当前对象锁,为了保证这一点,该方法必须方法synchronized代码块当中
     wait和sleep的区别:wait是进入等待并释放当前对象锁,sleep进入休眠不释放当前锁。
  3. 关于notify
     唤醒当前对象锁的线程(如果有多个,则随机唤醒一个)
     被唤醒的线程不会立即执行,而是等待当前线程释放了锁之后和其他线程进行一般性竞争获取锁
     和wait方法一样,必须保证调用时已经获取对象锁,所以也要在synchronized代码块中
  4. 关于线程通信
     既可以用synchronized,wait,notify等传统线程模型实现,也可以使用java提供的专门实现多线程的工具包来实现:java.util.concurrent.lock工具包下有Lock和Condition两个好用的工具哦
     Lock相对于传统模型synchronized方法更加面向对象,因为这里锁,本身就是一个对象
     Lock锁的话,执行完毕后,要显式的手动执行lock.unlock()来解锁,因为synchronized是JVM层面实现的,系统可以监控锁的释放与否,而Lock是代码层面实现的,所以尽量使用final子句来实现,保证不会遇到异常不能解锁。
    代码参考示例:
     Lock lock=new ReentrantLock();
              Condition condition=lock.newCondition();
              //创建一个变量控制执行main还是sub
              private boolean isSub=true;
              public void sub(int i){
                  lock.lock();
                  try {
                       //当不是sub时,等待
                       while (!isSub) {
                            try {
                                 condition.await();
                            } catch (Exception e) {
                                 e.printStackTrace();
                            }
    
                       }
                       for(int j=1;j<=10;j++){
                            System.out.println("sub Thread sequece of "+ j+",loop of "+i);
                       }
                       isSub=false;
                       condition.signal();//相当于notify
                  } finally {
                       lock.unlock();
                  }
              }
    

    还有一个问题就是,在等待Condition时,有可能出现虚假唤醒(spuriouswakeup),所以这里使用while做调节而不是if条件判断。

  5. 读写锁
     关于读写锁,读数据也要加锁,目的是防止读到未写入完成的数据,但不会限制其他的读线程
    简单的来说读写锁就是读锁和写锁互斥,写锁和写锁互斥,读锁和读锁不互斥。读写锁的目的是同一把锁读锁既可以与写锁互斥,又可以跟其他读锁共享。

转载注明地址:http://www.chengxuyuans.com/javabase/105992.html