多线程3

线程安全

线程可能会出现这些情况

 导致两个线程不能达到自己想要去循环的次数,可能两个线程各10000,那么他们就会出现不到5000甚至不到5000的情况。

出现线程的不安全原因: 

1.线程在系统中是随机调度,抢占式执行的.[线程不安全的, 罪魁祸首,万恶之源]。

无法改变!

2.当前代码中, 多个线程同时修改同一个变量

一个线程修改同一个变量 =>没事.

多个线程读取同一个变量 =>没事. 每次读到的结果都是固定的
多个线程修改不同的变量 =>没事.你改你的,我改我的,不影响

3.线程针对变量的修改操作,不是"原子"的

不可拆分的最小单位。

4.内存可见性问题,引起的线程不安全
5.指令重排序, 引起的线程不安全

解决问题

原因1.无法用实际行动干预,除非重写源代码才可。 

原因2,是一个切入点,但是在 java 中,这种做法,不是很普适,只是针对一些特定场景是可以做到的

 String 是 不可变 对象

java 标准库把 String 设计成不可变对象原因:

1.很好的保证线程安全
2.有稳定的 hash 值

3.方便在常量池中缓存.

原因3,这是解决线程安全问题,最普适的方案.

可以通过一些操作,把上述一系列“非原子"的操作,打包成一个"原子"操作.

关于锁,主要的操作是两个方面
1)加锁 t1 加上锁之后, t2 也尝试进行加锁,就会阻塞等待 (都是系统内核控制)(在java 中就能看到 BLOCKED 状态)
2)解锁 直到 t1 解锁了之后, t2 才有可能拿到锁(加锁成功)

举个例子

一个坑,两个人上,当一个人占坑的时候==加锁,等这个人上完了=解锁。这时候第二个人才可能有机会上厕所,当出现第三个人的时候,第二个人会和第三个人一起枪锁。

如果你两个线程,针对不同的坑位加锁,不会产生互斥的(也称为 锁竞争/锁冲突)

只有是两个线程(人)针对同一个坑位加锁,才有互斥~~

锁的小结:


1.锁涉及到两个核心操作
加锁 解锁
2.锁的主要特性: 互斥
一个线程获取到锁之后,另一个线程也尝试加这个锁,就会阻塞等待,(也叫做锁竞争/锁冲突)
3. 代码中, 可以创建出多个锁.
只有多个线程竞争同一把锁,才会产生互斥,针对不同的锁, 则不会

Java 中随便拿一个对象, 都可以作为加锁的对象.(这个是 Java 中特立独行的设定)其他语言中(C++,Go, Python....) 都是只有极少数特定的对象可以用来加锁.

synchronized(锁)

synchronized后面带上()里面就是写的“锁对象

synchronized下面跟着{}当进入到代码块,就是给上述()锁对象进行了加锁操作当出了代码块,就是给上述()锁对象进行了解锁操作看不到形如lock()unlock0方法的(其他语言都是这么搞的)

public class Test {
    public static int count;
    public static void main(String[] args) throws InterruptedException {
        Object o=new Object();
        Thread t1=new Thread(()->{
            for (int i=0;i<50000;i++){
            synchronized (o){
                count++;
            }
            }
        });
        Thread t2=new Thread(()->{
            for (int i=0;i<50000;i++){
                synchronized (o){
                    count++;
                }
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(count + "count");
    }
}

针对同一个对象加锁后count==100000,如果synchronized锁住的东西不同,则会不会产生互斥现象。count!=100000

 

修饰普通方法,相当于针对 this 加锁

修饰静态方法, 相当于针对 类对象 加锁

synchronized (o)放在for循环外面就会降低效率。
synchronized (this)这样的时候所指的就是调用的对象。

还有一个特殊的是static方法.没有this!

synchronized static void func(){
}

synchronized修饰static方法相当于针对该类的类对象加锁~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值