多线程下修改同一变量
1.对累加方法加上synchronized
1.如果用synchronized (this)
会不起作用
2.最后是在count++ 新写了个方法,加上synchronized关键字
public class Demo {
int counter = 0;
public synchronized void sellTicket() {
counter++;
}
class CountThread extends Thread {
public void run() {
for (int i = 0; i < 10000; i++) {
sellTicket();
}
}
}
}
@Test
public void testDemo() {
Demo demo = new Demo();
for (int i = 0; i < 2; i++) {
demo.new CountThread().start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("total=" + demo.counter);
}
2.加类锁
synchronized (CountThread.class)
public class Demo {
int counter = 0;
class CountThread extends Thread {
public void run() {
for (int i = 0; i < 10000; i++) {
synchronized (CountThread.class) {
counter++;
}
}
}
}
}
@Test
public void testDemo() {
Demo demo = new Demo();
for (int i = 0; i < 2; i++) {
demo.new CountThread().start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("total=" + demo.counter);
}
3.int换成AtomicInteger
public class Demo {
AtomicInteger counter = new AtomicInteger();
class CountThread extends Thread {
public void run() {
for (int i = 0; i < 10000; i++) {
synchronized (CountThread.class) {
counter.incrementAndGet();
}
}
}
}
}
@Test
public void testDemo() {
Demo demo = new Demo();
for (int i = 0; i < 2; i++) {
demo.new CountThread().start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("total=" + demo.counter);
}
AtomicInteger的底层实现原理:采用了基于CAS的技术:
CAS算法的过程是这样的,它包含三个参数CAS(V,E,N)。V表示要更新的变量,E表示预期值,N表示新值。仅当V值等于E值时,才会将V的值设为N。如果V值和E值不同,说明已经有了其他线程做了修改,则当前线程什么都不做。最后,CAS返回当前V的真实值。CAS是抱着乐观的态度来的,它总认为自己可以完成。当有多个线程竞争时,总有一个线程能够完成。其他线程则继续尝试,直到任务完成。CAS操作即使没有锁,也能发现其他线程对当前线程的干扰,并进行正确处理。
由于CAS的这种机制,它是非阻塞的,天生对死锁免疫。
其中value值用的volatile修饰 保证线程可见性