Java多线程之线程安全

Java多线程之线程安全

概念

  当多个线程访问某一个类(对象或方法时),这个类始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的。

反例

  

public class Mythread extends Thread{

    private int count = 5;

    @Override
    public void run() {
        while (count > 0){
            count--;
            System.out.println(Thread.currentThread().getName() + "正在执行:" + count);
        }
    }

    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        Thread t1 = new Thread(mythread,"t1");
        Thread t2 = new Thread(mythread,"t2");
        Thread t3 = new Thread(mythread,"t3");
        Thread t4 = new Thread(mythread,"t4");
        Thread t5 = new Thread(mythread,"t5");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
}

结果如下:
  t1正在执行:4
  t1正在执行:2
  t1正在执行:1
  t1正在执行:0
  t2正在执行:3

  上述代码中,我们的期望结果是 打印count的值应为: 4 3 2 1 0,与预期结果不相符合,所以Mythread这个类线程不安全,简单来讲,就是有多个线程去操作count这个变量,但是count变量的值并不是我们期望的值,这就引发了线程安全的问题。

正例

public class Mythread extends Thread{

    private int count = 5;

    @Override
    public synchronized void run() {
        while (count > 0){
            count--;
            System.out.println(Thread.currentThread().getName() + "正在执行:" + count);
        }
    }

    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        Thread t1 = new Thread(mythread,"t1");
        Thread t2 = new Thread(mythread,"t2");
        Thread t3 = new Thread(mythread,"t3");
        Thread t4 = new Thread(mythread,"t4");
        Thread t5 = new Thread(mythread,"t5");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
}

结果如下:
  t2正在执行:4
  t2正在执行:3
  t2正在执行:2
  t2正在执行:1
  t2正在执行:0

可以在任意对象及方法上加锁,而加锁的代码称为“互斥区”或“临界区”,加了synchronized关键字后,  当多个线程访问MyThead的run方法时,以排队的方式进行处理(这里的排队是按照CPU分配的先后顺序而定的),一个线程想要执行synchronized代码体内容,,必须得等上一个线程执行完,才能拿到锁,如果拿不到锁,这个线程就会不断的尝试获得这把锁,直到拿到为止,而且多个线程同时去竞争这把锁

总结

如果想要达到线程安全,大概有以下办法:

  • 封住:通过封装,我们可以将对象内部状态隐藏,保护起来。
  • 不可变

线程安全需要保证几个基本特征:

  • 原子性:简单说就是相关操作不会中途被其他线程干扰,一般通过同步机制实现。
  • 可见性:是一个线程修改了某个共享变量,其状态能够立即被其他线程知晓,通常被解释为将线程本地状态反映到主内存上。
  • 有序性:是保证线程串行语义,避免指令重排等。

  能够实现线程安全得方法很多,上面synchronized虽然能保证线程安全,但是会导致锁竞争问题,比如,当有100个线程在同时操作一个变量,当线程1执行完毕后,后面的线程2到线程100,一共99个线程,都会去争夺这一把所,产生非常激烈的锁竞争问题,这可能会导致服务器的CPU使用率过高

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值