Java多线程学习(三)

用关键字synchronized声明方法是有弊端的。

  1. synchronized同步代码块的使用:当两个并发线程访问桶一个对象object中的synchronized(this)同步代码块是,一段时间内只能有一个线程被执行,另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

    synchronized(this){
    }
  2. 当一个线程访问object的一个synchronized同步代码块时,另一个线程仍然可以访问该object对象中的非synchronized(this)同步代码块。因此可以较同步方法提高效率。

  3. object对象中的代码,不在synchronized块中就是异步执行,在synchronized块中就是同步执行。

  4. synchronized代码块之间的同步性:在使用synchronized(this)同步代码块时需要注意的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对同一个object中所有其他synchronized(this)同步代码块的访问将被阻塞,这说明synchronized使用的对象监视器是同一个。必须等待当前synchronized(this)同步代码块执行完之后,才能访问其他的synchronized(this)同步代码块。

  5. 同synchronized方法一样,synchronized(this)同步代码块也是锁定当前对象的。

  6. 将任意对象作为对象监视器

    6.1 多个线程调用同一个对象的不同名称的synchronized同步方法或synchronized(this)同步代码块是,调用的效果就是按顺序执行,同步的,阻塞的。

    6,2 synchronized代码块支持对任意对象作为对象监视器来实现同步的功能,大多是实例变量及方法参数。使用方法为synchronized(非this对象  x){}

    在多个线程持有的对象监视器为同一个对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象 x)同步代码块中的代码。

     6.3 锁非this对象具有好处:synchronized(非this对象)同步代码块与同步方法和synchronized(this)同步代码块是异步的,不会与其他锁this同步方法争抢this锁,则可大大提高运行效率。

    6.4 使用synchronized(非this对象)同步代码块进行同步操作时,对象监视器必须是同一个对象,否则就有多把锁,结果为异步运行。

    6.5使用synchronized(非this对象)同步代码块可以避免脏读问题。

  7. synchronized(非this对象 x)同步代码块是将x对象本身作为“对象监视器”,这样就有以下三个结论:

    1)当多个线程同时执行synchronized(x)同步代码块时呈同步效果;

    2)当其他线程执行x对象中的synchronized同步方法时呈同步效果;

    3)当其他线程执行x对象方法里的synchronized(this)代码块时也呈同步效果。

  8. 静态同步synchronized方法与synchronized(class)代码块

    关键字synchronized可以应用在static静态方法上,即对当前的*.Java文件对应的Class类进行持锁。synchronized关键字加到静态方法上是给Class类上锁,而synchronized关键字加到非static方法上是给对象上锁。

    Class锁可以对类的所有对象实例起作用。

    同步synchronized(class)代码块与synchronized static方法的作用一样。synchronized(Service。class)。

  9. 数据类型String的常量池特性

    1)在JVM中具有常量缓存池的功能

    String a = "A";
    String b = "A";
    System.out.println(a == b);
    
    输出结果为:true

    将synchronized(string)同步块与String联合使用时,要注意常量池带来的一些例外。如线程A和线程B持有的锁都是“aa”,由于“aa”的缓存池属性,他们持有的是同一个锁,所以有可能其中一个线程永远无法执行。

  10. 多线程的死锁

    死锁:不同的线程都在等待根本不肯被释放的锁,从而导致所有的任务都无法继续完成。

    public void run(){
     if(username.equals("a")){
         synchronized(lock1){
             //todo
             synchronized(lock2){
                 //todo
             }
         }
     }
     if(username.equals("b")){
            synchronized(lock2){
                //todo
                synchronized(lock1){
                    //todo
                }
            }
        }
    }

     可以使用JDK自带的工具来检测是否有死锁的现象:1)jps--查询出线程id号;2)jstack -l 线程id号  --列出Java stack信息。

  11. 内置类与静态内置类

    1)内置类中有两个同步方法,但使用不同的锁,则运行结果是异步的。

  12. 锁对象的改变

    在将任何数据类型作为同步锁时,需要注意的是,是否有多个线程同时持有锁对象,如果同时持有相同的锁对象,那么这些线程之间就是同步的,如果分别获得锁对象,这些线程之间就是异步的。

    只要对象不变,即使对象的属性被改变,运行的结果还是同步的。

你可能感兴趣的:(Java多线程学习(三))