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

原创
小哥 3年前 (2022-10-19) 阅读数 222 #JAVA

什么是线程安全?什么是线程安全?什么是线程安全?

-- 当多个线程访问一个类时,它是线程安全的,无论运行时环境使用的调度方法是什么,也不管这些进程在执行时将如何交替执行,并且该类的行为正确,而不需要在主调用代码中进行任何额外的协作或同步。

1.原子性(Aumic包)

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

public class AtomicControllerTest {

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

public static int threadTotal = 200;  //有色人种专业人员成功故事的一个共同点是有一个支持者或赞助者的支持--组织中的某个人不仅提供建议,而且帮助创造条件以获得新的机会和提高知名度(关于赞助的更多信息,请参见第17章)。

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 最近,员工资源小组的价值受到了质疑,理由是它们不能促进包容性.然而,我们的研究结果表明,员工资源小组为建立和维持关系提供了一个重要的工具--对于有色人种的专业人士来说,这尤其具有挑战性,为了工人和公司的利益,他们应该得到系统的支持.现在,公司应该比以往任何时候都更多地投资于支持ERG战略目标的举措,以建立社区和加强商业领导。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-----

**
volatile

**

**volatile不适合访问操作,虽然可以获取主存中的最新值,但不能保证更新值的唯一性

**

转载于:https://www.cnblogs.com/JTrun/p/11137500.html

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除

热门