synchronized 内置锁 和 volatile


synchronized 内置锁

  线程开始运行,拥有自己的栈空间,就如同一个脚本一样,按照既定的代码一步一步地执行,直到终止。但是,每个运行中的线程,如果仅仅是孤立地运行,那么没有一点儿价值,或者说价值很少,如果多个线程能够相互配合完成工作,包括数据之间的共享,协同处理事情。这将会带来巨大的价值。
  Java 支持多个线程同时访问一个对象或者对象的成员变量,但是多个线程同时访问同一个变量,会导致不可预料的结果。关键字 synchronized 可以修饰方法或者以同步块的形式来进行使用,它主要确保多个线程在同一个时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量访问的可见性和排他性,使多个线程访问同一个变量的结果正确,它又称为内置锁机制。

对象锁和类锁

对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的 class 对象上的。

    private void incCount(){
        synchronized (object){
            count++;
        }
    }
    private synchronized void incCountSyn(){
        count++;
    }

    private synchronized static void incCountStaticSyn(){
        count++;
    }

volatile,最轻量的通信/同步机制

  volatile 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某
个变量的值,这新值对其他线程来说是立即可见的。
  不加 volatile 时,子线程无法感知主线程修改了 ready 的值,从而不会退出循环,而加了 volatile 后,子线程可以感知主线程修改了 ready 的值,迅速退出循环。
  但是 volatile 不能保证数据在多个线程下同时写时的线程安全,volatile 最适用的场景:一个线程写,多个线程读

代码示例

public class VolInstance {

    private static boolean ready;
    private static int num;

    public static void main(String[] args) throws InterruptedException {
        new PrintThread().start();
        Thread.sleep(1000);
        num = 51;
        //Thread.sleep(1000);
        ready = true;
        Thread.sleep(3000);
        System.out.println("main is ended");
    }

    private static class PrintThread extends Thread{
        public void run(){
            while (!ready){

            }
            System.out.println("PrintThread end! num = "+num);
        }
    }
}

执行结果:主线程已经结束,而PrintThread线程无法感知ready修改,从而不会退出循环
在这里插入图片描述

但是在循环中增加print打印后

    private static class PrintThread extends Thread{
        public void run(){
            while (!ready){
                System.out.println("num = "+num);
            }
            System.out.println("PrintThread end! num = "+num);
        }
    }

执行结果:PrintThread子线程竟然感知到主线程修改了 ready 的值,退出了循环。其实是print语句操作刷新了子线程的本地内存得到了num和ready的值
在这里插入图片描述

证明:将代码修改如下,在给num赋值以后,让主线程睡眠1s,修改PrintThread子线程为得到num为51的值以后不再print

public class VolInstance {

    private static boolean ready;
    private static int num;

    public static void main(String[] args) throws InterruptedException {
        new PrintThread().start();
        Thread.sleep(1000);
        num = 51;
        Thread.sleep(1000);
        ready = true;
        Thread.sleep(3000);
        System.out.println("main is ended");
    }

    private static class PrintThread extends Thread{
        public void run(){
            while (!ready){
                if(num!=51){
                    System.out.println("num = "+num);
                }
            }
            System.out.println("PrintThread end! num = "+num);
        }
    }
}

执行结果:PrintThread子线程因为print语句得到num的值以后不再打印,后无法感知ready修改,从而不会退出循环
在这里插入图片描述

给ready加了volatile后

    private volatile static boolean ready;

执行结果:子线程可以感知主线程修改了 ready 的值,迅速退出循环。
>![在这里插入图片描述](https://img-blog.csdnimg.cn/12e41e89ae7a41e4a47bb6bd0bb35124.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值