多线程下volatile 关键字的作用

Volatile 关键字

作用:
Volatile 关键字是多线程下,最小轻量级的同步机制。
过程:
首先Volatile 修饰的成员变量应该是多个线程共享的资源,每个线程在访问共享变量的时候,线程的工作内存中都会存有这个变量的一个拷贝,变量本身还是保存在共享内存中。对这个变量的访问必须从共享内存刷新一次。最新的修改写回共享内存,保证了字段的可见性,但是并没有保证操作对该变量操作的原子性。(多线程下原子性:指的是原子操作的最小粒子,指不可被中断的一个或一系列操作)

synchronized 关键字 修饰方法和修饰对象的区别(实践是检验真理的唯一标准)

首先是synchronized 修饰方法时,运行main 方法看到的效果是 doSomething 和 getSomething 基本上是同步执行的。 由此可见 synchroized 修饰的方法时,锁的是对象本身。

package com.chen.springboot.thread.signal;
import java.util.concurrent.CountDownLatch;
public class Entiry {
    private static volatile Entiry entiry; //  创建一个单列实例
    private static CountDownLatch countDownLatch = new CountDownLatch(1);  // 发令枪保证 多线程并发
    public static Entiry instanceEntity(){  // 懒汉模式创建 单列
        if(entiry==null){
            synchronized (Entiry.class){
                if(entiry==null){
                    entiry = new Entiry();
                }
            }
        }
        return entiry;
    }

    public synchronized void doSomething(String index){ //两个同步方法
        System.out.println(index+"获取到了 doSomething");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void getSomething(String idex){ //两个同步方法
        System.out.println(idex+"获取到了 getSomething");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        for(int i=0;i<20;i++){
            Thread t = new Thread(new CRunnable(i));
            t.start();
        }
        countDownLatch.countDown();
    }


    static class CRunnable implements Runnable{
       private Integer index;
        public CRunnable(Integer index) {
            this.index = index;
        }
        @Override
        public void run() {
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Entiry entiry = Entiry.instanceEntity();
            //多线程运行 为了区别 让一半的线程执行同步方法A 另一半的线程执行同步方法B
            if(index%2==0){
                entiry.doSomething(String.valueOf(index));
            }else {
                entiry.getSomething(String.valueOf(index));
            }
        }
    }

}

synchronized 修饰this,效果和锁方法是一样的。

package com.chen.springboot.thread.signal;

import java.util.concurrent.CountDownLatch;

public class Entiry {

    private static volatile Entiry entiry; //  创建一个单列实例

    private static CountDownLatch countDownLatch = new CountDownLatch(1);  // 发令枪保证 多线程并发

    public static Entiry instanceEntity(){  // 懒汉模式创建 单列
        if(entiry==null){
            synchronized (Entiry.class){
                if(entiry==null){
                    entiry = new Entiry();
                }
            }
        }
        return entiry;
    }

    public  void doSomething(String index){ //两个同步方法
        synchronized (this){
            System.out.println(index+"获取到了 doSomething");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public  void getSomething(String idex){ //两个同步方法
        synchronized (this){
            System.out.println(idex+"获取到了 getSomething");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        for(int i=0;i<20;i++){
            Thread t = new Thread(new CRunnable(i));
            t.start();
        }
        countDownLatch.countDown();
    }


    static class CRunnable implements Runnable{

        private Integer index;

        public CRunnable(Integer index) {
            this.index = index;
        }

        @Override
        public void run() {
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Entiry entiry = Entiry.instanceEntity();
            //多线程运行 为了区别 让一半的线程执行同步方法A 另一半的线程执行同步方法B
            if(index%2==0){
                entiry.doSomething(String.valueOf(index));
            }else {
                entiry.getSomething(String.valueOf(index));
            }
        }
    }
}

区别:锁方法时是将整个方法体都被锁住,对于有些不需要执行同步的步骤来说是这样锁是不合理的,所以一般都用synchronized关键字赖控制锁的粒度。

锁如果加载静态方法或者时静态类时,效果是什么样呢?

两个同步方法都加了锁住了类,单列实例还是原来的效果。多个实现类时发现效果也是一样的。可见锁住类时,不管多个实现类执行锁类的方法时都是同步的。原因是:多个实现类共享一个class对象。

    public  void doSomething(String index){ //两个同步方法
        synchronized (Entiry.class){
            System.out.println(index+"获取到了 doSomething");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public  void getSomething(String idex){ //两个同步方法
        synchronized (Entiry.class){
            System.out.println(idex+"获取到了 getSomething");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

当synchronized 关键字锁静态方法时,效果也是一样的这就可以进一步证明静态方法是属于累的,跟实例没有关系

    public static synchronized void doSomething(String index){ //两个同步方法
            System.out.println(index+"获取到了 doSomething");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    }

    public static synchronized void getSomething(String idex){ //两个同步方法
            System.out.println(idex+"获取到了 getSomething");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。