1.synchronized关键字 

     1.1什么意思

  synchronized关键字主要是用来解决多个线程访问资源的同步性,也就是保证被修饰的方法或者代码块任意时刻都只能有一个线程在执行。

  底层实现是在修饰的前后加上minitorenter/minitorexit:

  minitorenter:当需要获取锁的时候,会检查锁的计数器,如果是0,可以获取;如果是1,则不能获取

  minitorexit:当执行完了,会把锁的计数器设置为0.

     1.2如何使用(3种方法)

  1.2.1修饰实例方法:作用相当于对当前的实例对象加锁

  1.2.2修饰静态方法:相当于对当前的类加锁,也就是说当前类的所有实例对象在不同的线程中,同一时间最多只能有一个线程调用该静态方法。

  1.2.3修饰代码块:给指定的Object加锁,需要注意的是,最好不要用该关键词修饰String,因为在JVM中,字符串常量词存在缓存功能,本意是给2个线程加不同的锁,但是放入的是String的话,2个线程持有的是相同的锁,导致某一个线程无法正常运行。

  

public class SynTest {
    public static class Threads implements Runnable{
        @Override
        public void run() {
            mbClass mb0 = new mbClass();
            try {
//                mb0.say();
//                mb0.says();
                  mb0.sayss();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public static class mbClass{
        synchronized public void say() throws InterruptedException{
            for(int i = 0; i<10;i++) {
                System.out.print(i);
            }
            System.out.println("开始等待");
            Thread.sleep(3000);
            System.out.println("等待结束");
        }
        synchronized public static void says() throws InterruptedException{
            for(int i = 0; i<3;i++) {
                System.out.print("k");
            }
            System.out.println("开始等待+");
            Thread.sleep(3000);
            System.out.println("等待结束+");
        }

        public void sayss() throws InterruptedException{
            synchronized(mbClass.class) {
                System.out.println("开始+");
                for(int i = 0; i<3;i++) {
                    System.out.print("QQQ");
                }
                Thread.sleep(3000);
                System.out.println("结束+");
            }
        }
    }


    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Threads p = new Threads();
        new Thread(p,"线程1").start();
        Threads q = new Threads();
        new Thread(q,"线程2").start();
    }
}

  这里就不放结果了,可以把注释的2种方法,特别是say()和says()之间的区别。

     1.3synchronized和Lock的区别

  首先synchronized是java的关键字,是JVM层面实现的,而Lock是个接口,是JDK层面实现的,也就意味着,Lock具有比synchronized更多的功能。

  其次,synchronized不需要用户手动的释放锁,但是Lock需要手动释放,如果不释放有可能会造成死锁的发生。

  synchronized其实是有许多缺点的:第一,当线程被阻塞时,比如sleep(),其他的线程会一直等待下去,很浪费时间;第二,对于多个线程来说,读操作其实是可以多个线程共享的,syn就不能实现这个要求。第三,syn是不能知道一个线程是否能够取得了锁。

2.volatile关键字

     2.1 什么意思/从内存看作用

  第一个作用就是防止指令重排,创建一个新的对象,第一步,分配内存空间,第二步,初始化,第三步,指向分配的内存地址。在单线程的时候一般不会出现问题,但是在多线程的时候,有可能出现132的情况,而volatile就可以防止该可能的发生(有序性)

  第二个作用就是保证变量在多线程情况下的可见性。(可见性)

     2.2和synchronized的区别

  并发的3个特性便是:原子性,可见性,有序性。

  而synchronized可以保证原子性。

  二者不同的是,

  第一:syn可以修饰方法,代码块,而volatile只能修饰变量

  第二:正如上面所说syn可以保证原子性,可见性,但是volatile只能保证可见性

  第三:二者的作用,syn是保证多个线程访问资源的同步性,volatile是解决变量在多个线程之间的可见性。

     

posted on 2021-04-18 00:18  Refuse_to_be_simple  阅读(106)  评论(0编辑  收藏  举报