• 关于多线程的几点总结


    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. 读写锁
       关于读写锁,读数据也要加锁,目的是防止读到未写入完成的数据,但不会限制其他的读线程
      简单的来说读写锁就是读锁和写锁互斥,写锁和写锁互斥,读锁和读锁不互斥。读写锁的目的是同一把锁读锁既可以与写锁互斥,又可以跟其他读锁共享。
  • 相关阅读:
    web前端常见面试题
    pyhton课堂随笔-基本画图
    安装和启动json-server
    Idea破解注册码
    MongoDB基本增删改查
    MogonDB安装及配置
    python和jupyter安装
    web中静态资源和动态资源的概念及区别
    nodejs基础(三)
    C#进程、线程、CPU
  • 原文地址:https://www.cnblogs.com/jeyson/p/6222423.html
Copyright © 2020-2023  润新知