线程学习记录01-什么是线程安全

2017-06-21  本文已影响0人  绝世懒人

线程安全概念:当多个线程访问某个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类就是线程安全的。
synchronized:可以在任意对象及方法上加锁,而加锁的这段代码称为“互斥区” 或“临界区”

示例:

public class MyThread extends Thread {

private int count = 5 ;

@Override
public void run() {
    count -- ;
    System.out.println(this.currentThread().getName() + ": count is " + 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();
}}

如上代码,方法上我们并没有加锁。同时运行5个线程,期望count能够按照我们预期的依次递减。但是结果如下

image.png

其中并没有按照我们预期中的进行递减,这是因为当多个线程访问MyThread的run方法时,是以CPU分配的先后顺序进行的,并不是按照代码的先后顺序。所以很有可能当某段代码还没执行完,CPU就把这个资源分配给其他线程了,导致共享变量的错乱。
因此,做出如下修改:

public class MyThread extends Thread {

private int count = 5 ;

@Override
public synchronized void run() {
    count -- ;
    System.out.println(this.currentThread().getName() + ": count is " + 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();
}}
image.png

在run方法上加上synchronize,使其成为一段互斥的代码。当线程尝试执行synchronize修的代码时,会先去尝试获取锁,拿到锁则执行代码。拿不到则会不断的尝试获取这把锁,直到拿到为止,而且是多个线程同时去竞争这把锁(比如1000个线程,只有一个线程能拿到锁,其他999个线程去竞争,对我们CPU的压力就比较大了,应该尽量避免)

上一篇下一篇

猜你喜欢

热点阅读