什么是线程安全性?如何线程安全

什么是线程安全?

 --当多个线程访问某个类时,不管运行环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的协同或者同步,这个类都能表现出正确的行为,那么这个类是线程安全的。

 1.原子性(Aumic包)

AutomicXXX类  :采用CAS机,即 unsafe.compare.AndSwapInt

public class AtomicControllerTest {


    public static int clientTotal = 5000; //请求总数

    public static int threadTotal = 200;  //同时并发的线程数

    public static AtomicInteger count =  new AtomicInteger(0);

    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newCachedThreadPool();  //创建线程池
        final Semaphore semaphore = new Semaphore(threadTotal);  //信号量(线程数)
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);  //计数器  (把请求计数)
        for(int i =0 ; i < clientTotal ; i++){
            executorService.execute(()->{
                try {
                    semaphore.acquire();//信号量  判断进程是否执行
                    add();
                    semaphore.release();
                } catch (Exception e){
                    log.error("Exception:", e);
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();  //当所有请求结束
        executorService.shutdown();
        log.info("count:{}", count);

    }
    private static void add(){
        count.incrementAndGet();
    }
}

上面的代码是线程安全的,要是将AutomicInteger换成Integer,add方法也随着变成count++,线程将是不安全的。

incrementAndGet中的getAndAddInt是最为关键的代码。

var1 是传进来的对象(count), 如果执行3+1操作,var2是当前的值3,var 4 是1

var5 是底层的值,也就是从主内存拿到的值,由于其他线程也在进行操作,工作内存一直想主内存进行存取操作,主内存的值一直在变化

CAS操作的核心也就是保证从主内存拿到的值,是预期获得的值并没有被其他线程更改,所以在上面的方法中,一直在进行while操作,比较var2 和 var 5,

一旦相同,才会进行相加的操作。主内存和工作内存的运行图如下:

synchronized:
1.修饰方法和修饰一个类时,效果一致,先获得资源的线程,先运行,其余访问改资源的线程需要等待
package com.justrun.threadthink.sync;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
public class SynchronizedExample2 {

    // 修饰一个类
    public static void test1(int j) {
        synchronized (SynchronizedExample2.class) {
            for (int i = 0; i < 10; i++) {
                log.info("test1 {} - {}", j, i);
            }
        }
    }

    // 修饰一个静态方法
    public static synchronized void test2(int j) {
        for (int i = 0; i < 10; i++) {
            log.info("test2 {} - {}", j, i);
        }
    }

    public static void main(String[] args) {
        SynchronizedExample2 example1 = new SynchronizedExample2();
        SynchronizedExample2 example2 = new SynchronizedExample2();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() -> {
            example1.test2(1);
        });
        executorService.execute(() -> {
            example2.test2(2);
        });
    }
}
 

11:42:20.273 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 1 - 0
11:42:20.298 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 1 - 1
11:42:20.298 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 1 - 2
11:42:20.298 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 1 - 3
11:42:20.298 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 1 - 4
11:42:20.298 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 1 - 5
11:42:20.298 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 1 - 6
11:42:20.298 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 1 - 7
11:42:20.298 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 1 - 8
11:42:20.298 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 1 - 9
11:42:20.298 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 2 - 0
11:42:20.298 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 2 - 1
11:42:20.298 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 2 - 2
11:42:20.299 [pool-1-thread-2] INFO com.justrun.threadthink.syn

package com.justrun.threadthink.sync;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
public class SynchronizedExample1 {

    // 修饰一个代码块
    public void test1(int j) {
        synchronized (this) {
            for (int i = 0; i < 10; i++) {
                log.info("test1 {} - {}", j, i);
            }
        }
        log.info("test-----", j);
    }

    // 修饰一个方法
    public synchronized void test2(int j) {
        for (int i = 0; i < 10; i++) {
            log.info("test2 {} - {}", j, i);
        }
    }

    public static void main(String[] args) {
        SynchronizedExample1 example1 = new SynchronizedExample1();
        SynchronizedExample1 example2 = new SynchronizedExample1();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() -> {
            example1.test1(1);
        });
        executorService.execute(() -> {
            example2.test1(2);
        });
    }
}

c.SynchronizedExample2 - test2 2 - 3
11:42:20.299 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 2 - 4
11:42:20.299 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 2 - 5
11:42:20.299 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 2 - 6
11:42:20.299 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 2 - 7
11:42:20.299 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 2 - 8
11:42:20.299 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample2 - test2 2 - 9

Process finished with exit code 0

2。syhcnhronized修饰一个代码块和修饰一个方法,其原理大致一致,如果代码块修饰的整个方法的内容,那它们是一致的

随机调度资源,每个线程都有机会得到资源
package com.justrun.threadthink.sync;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
public class SynchronizedExample1 {

    // 修饰一个代码块
    public void test1(int j) {
        synchronized (this) {
            for (int i = 0; i < 10; i++) {
                log.info("test1 {} - {}", j, i);
            }
        }
        log.info("test-----", j);
    }

    // 修饰一个方法
    public synchronized void test2(int j) {
        for (int i = 0; i < 10; i++) {
            log.info("test2 {} - {}", j, i);
        }
    }

    public static void main(String[] args) {
        SynchronizedExample1 example1 = new SynchronizedExample1();
        SynchronizedExample1 example2 = new SynchronizedExample1();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() -> {
            example1.test1(1);
        });
        executorService.execute(() -> {
            example2.test1(2);
        });
    }
}
 

11:52:20.619 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 1 - 0
11:52:20.647 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 1 - 1
11:52:20.619 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 2 - 0
11:52:20.647 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 1 - 2
11:52:20.647 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 2 - 1
11:52:20.647 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 1 - 3
11:52:20.647 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 2 - 2
11:52:20.647 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 1 - 4
11:52:20.647 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 2 - 3
11:52:20.647 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 1 - 5
11:52:20.647 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 1 - 6
11:52:20.647 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 1 - 7
11:52:20.647 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 1 - 8
11:52:20.647 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 1 - 9
11:52:20.647 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 2 - 4
11:52:20.647 [pool-1-thread-1] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test-----
11:52:20.647 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 2 - 5
11:52:20.647 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 2 - 6
11:52:20.647 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 2 - 7
11:52:20.647 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 2 - 8
11:52:20.647 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test1 2 - 9
11:52:20.647 [pool-1-thread-2] INFO com.justrun.threadthink.sync.SynchronizedExample1 - test-----



猜你喜欢

转载自www.cnblogs.com/JTrun/p/11137500.html
今日推荐