多线程与高并发2

1、synchronized关键字

概念:多个线程访问同一个资源需要上锁。

例如两个线程同时对1进行加法运算。第一个线程+1.等于二这个2,还没写回去时候。第二线程读到了1。再在1的基础上加1导致最终结果为2.是错误的。最终结果应该是3

所以一个线程对资源要进行独占。写完以后释放资源后。另外的线程才能进入,进行读写操作。
这就是synchronized关键字作用

package com.example.demo.gc1;

public class T{
    private int count = 100;
    private Object o = new Object();
    public void m(){
            synchronized (o){ // 任何线程想要执行下面的代码必须拿到o锁
                System.out.println(Thread.currentThread().getName()+"-"+count);
            }
        }
}

每次定义一个锁对象把他new出来太麻烦

package com.example.demo.gc2;

public class T {
    private int count = 10;
    public void m(){
        synchronized (this){
            count --;
            System.out.println(Thread.currentThread().getName()+"-"+count);
        }
    }
}

synchronized (this)锁住当前行

package com.example.demo.gc3;

public class T {
    private int count = 10;
    public synchronized void m(){
        count --;
        System.out.println(Thread.currentThread().getName()+"-"+count);
    }
}

synchronized锁对象

package com.example.demo.gc4;

public class T {
    private static int count = 10;
    public synchronized static void m(){
        count --;
        System.out.println(Thread.currentThread().getName()+"-"+count);
    }
    public static void mm(){
        synchronized (T.class){
            count --;
        }
    }
}

T.class针对静态方法,一般咋们的静态方法被调用。不用创建这个类对象。直接类名.方法。这里也是一个意思
synchronized (T.class)就代表锁的是T类对象

####面试题T.class是单例的吗?
一个class load到内存里是不是单例的。一般情况下是。如果是同一个classLoader空间那就是。不是同一个类加载器就不是。不同类加载器就不是单例。。。不是同一个加载器相互之间也不能访问。但是T.class能访问。那他就是单例

2、volatile内存可见性

未加锁出现的线程安全问题,来看一段代码

package com.example.demo.gc5;

public class T implements Runnable {
    private int count = 100;
    @Override
    public void run() {
        count -- ;
        System.out.println(Thread.currentThread().getName()+"-"+count);
    }

    public static void main(String[] args) {
        T t = new T();
        for (int i=0;i<100;i++){
            new Thread(t,"THREAD"+i).start();
        }
    }
}

在这里插入图片描述
volatile作用与变量这里。但不结合synchronized一样会有线程安全问题

package com.example.demo.gc5;

public class T implements Runnable {
    private volatile int count = 100;
    @Override
    public  void run() {
        count -- ;
        System.out.println(Thread.currentThread().getName()+"-"+count);
    }

    public static void main(String[] args) {
        T t = new T();
        for (int i=0;i<100;i++){
            new Thread(t,"THREAD"+i).start();
        }
    }
}

在这里插入图片描述

以下两种方法可以完成线程独占
1、volatile和synchronized结合用

package com.example.demo.gc5;

public class T implements Runnable {
    private volatile int count = 100;
    @Override
    public synchronized void run() {
        count -- ;
        System.out.println(Thread.currentThread().getName()+"-"+count);
    }

    public static void main(String[] args) {
        T t = new T();
        for (int i=0;i<100;i++){
            new Thread(t,"THREAD"+i).start();
        }
    }
}

2、只用synchronized

package com.example.demo.gc5;

public class T implements Runnable {
    private int count = 100;
    @Override
    public synchronized void run() {
        count -- ;
        System.out.println(Thread.currentThread().getName()+"-"+count);
    }

    public static void main(String[] args) {
        T t = new T();
        for (int i=0;i<100;i++){
            new Thread(t,"THREAD"+i).start();
        }
    }
}

在这里插入图片描述

####synchronized和volatile区别?
1、volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取
2、synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
3、volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
4、volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
5、volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
6、volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化

在使用synchronized时候就可以不用volatile了

package com.example.demo.gc6;

public class T implements Runnable {
    private int count = 100;
    @Override
    public synchronized void run() {
        count --;
        System.out.println(Thread.currentThread().getName()+"count = "+count);
    }

    public static void main(String[] args) {
        T t = new T();
        for (int i = 0; i < 100; i++) {
            new Thread(t,"THREAD"+i).start();
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值