java多线程变量同步_【Java多线程】共享变量&同步-异步容器&线程局部变量

共享变量 (Volatile Atomic)

volatile:当多个线程访问一个成员变量的时候,需要这个变量在多个线程中可见。

Atomic:Atomic方法对该变量的操作是原子性操作,颗粒度是到对这个变量的一次操作。

private static AtomicInteger count = new AtomicInteger(0);

count.incrementAndGet();

Atomic+synchronized :如果要保证多线程之间的原子性操作,也就是对一个变量进行多次Atomic方法操纵操作。那就需要加synchronized ,来 保证多线程间的原子性。

private static AtomicInteger count = new AtomicInteger(0);

count.incrementAndGet();

count.incrementAndGet();

count.incrementAndGet();

//多线程间他们不是原子性操作,如果需要原子性操作,需要在外层方法加synchronized

Volatile

原理:当线程操作该变量的时候会强制去主内存(堆)中去读取。使用方法如下

public class RunThread extends Thread{

private volatile boolean isRunning = true;

private void setRunning(boolean isRunning){

this.isRunning = isRunning;

}

public void run(){

System.out.println("进入run方法..");

int i = 0;

while(isRunning == true){

//..

}

System.out.println("线程停止");

}

public static void main(String[] args) throws InterruptedException {

RunThread rt = new RunThread();

rt.start();

Thread.sleep(1000);

rt.setRunning(false);

System.out.println("isRunning的值已经被设置了false");

}

}

volatile 变量本身不具备原子性。说明

public class VolatileNoAtomic extends Thread{

private static volatile int count;

private static void addCount(){

for (int i = 0; i < 1000; i++) {

//count++ ;

count.incrementAndGet();

}

System.out.println(count);

}

public void run(){

addCount();

}

public static void main(String[] args) {

VolatileNoAtomic[] arr = new VolatileNoAtomic[100];

for (int i = 0; i < 10; i++) {

arr[i] = new VolatileNoAtomic();

}

for (int i = 0; i < 10; i++) {

arr[i].start();

}

}

Atomic

如果要实现原子性(同步),可以使用Atomic类型的变量。如AtomicInteger、AtomicLong…

private static AtomicInteger count = new AtomicInteger(0);

但是,只能保证方法的原子性,不能保证多线程间的原子性。解决方法可以给方法synchronized 修饰,加说明

private static AtomicInteger count = new AtomicInteger(0);

//多个addAndGet在一个方法内是非原子性的,需要加synchronized进行修饰,保证4个addAndGet整体原子性

/**synchronized*/

public synchronized int multiAdd(){

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

count.addAndGet(1);

count.addAndGet(2);

count.addAndGet(3);

count.addAndGet(4); //+10

return count.get();

}

public static void main(String[] args) {

final AtomicUse au = new AtomicUse();

List ts = new ArrayList();

for (int i = 0; i < 100; i++) {

ts.add(new Thread(new Runnable() {

@Override

public void run() {

System.out.println(au.multiAdd());

}

}));

}

for(Thread t : ts){

t.start();

}

ThreadLocal

当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。用ThreadLocal可以一定程度减少锁竞争。使用方式如下

public class ConnThreadLocal {

public static ThreadLocal th = new ThreadLocal();

public void setTh(String value){

th.set(value);

}

public void getTh(){

System.out.println(Thread.currentThread().getName() + ":" + this.th.get());

}

public static void main(String[] args) throws InterruptedException {

final ConnThreadLocal ct = new ConnThreadLocal();

Thread t1 = new Thread(new Runnable() {

@Override

public void run() {

ct.setTh("张三");

ct.getTh();

}

}, "t1");

Thread t2 = new Thread(new Runnable() {

@Override

public void run() {

try {

Thread.sleep(1000);

ct.getTh();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}, "t2");

t1.start();

t2.start();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值