一、代码示例
public class LockTest {
int orderNum = 60000;//共享变量-库存6万
public void order() {
orderNum--;
}
@Test
public void Test() {
for (int i = 0; i < 6; i++) {
new Thread() {
@Override
public void run() {
for (int j = 0; j < 10000; j++) {
order();
}
}
}.start();
}
try {
Thread.sleep(3000);//等待让线程跑完
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("库存量: " + orderNum);
}
}
输出结果
库存量: 26096
正常来说,输出的结果应该是:库存量: 0,造成这个结果的原因就是线程不安全
二、使用synchronized 对代码进行优化
public class LockTest {
int orderNum = 60000;//共享变量-库存6万
Object object = new Object();
public void order() {
synchronized (object) {
orderNum--;
}
}
@Test
public void Test() {
for (int i = 0; i < 6; i++) {
new Thread() {
@Override
public void run() {
for (int j = 0; j < 10000; j++) {
order();
}
}
}.start();
}
try {
Thread.sleep(3000);//等待让线程跑完
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("库存量: " + orderNum);
}
}
输出结果:库存量: 0
三、使用AtomicInteger 保证线程安全
public class Atomicest {
AtomicInteger orderNum = new AtomicInteger(60000);
public void order() {
orderNum.decrementAndGet();
}
@Test
public void Test() {
for (int i = 0; i < 6; i++) {
new Thread() {
@Override
public void run() {
for (int j = 0; j < 10000; j++) {
order();
}
}
}.start();
}
try {
Thread.sleep(3000);//等待让线程跑完
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("库存量: " + orderNum);
}
}
输出结果:库存量: 0
优点:执行速度比synchronized 快很多
缺点:复杂的操作无法使用
比如:如果
public void order() {
//有很多业务逻辑
}
此时就无法使用
四、使用ReentrantLock保证线程安全
public class ReentrantTest {
int orderNum = 60000;//共享变量-库存6万
Lock lock = new ReentrantLock();//jdk1.5开始才有这种锁
public void order() {
lock.lock();//加锁 加锁和解锁都是自己很明显的写出来的,所以也叫做显式锁
try {
orderNum--; //可以抛出异常代码
} finally {//标准的规范的lock锁的加锁和解锁的写法
lock.unlock();//解锁
}
}
@Test
public void Test() {
for (int i = 0; i < 6; i++) {
new Thread() {
@Override
public void run() {
for (int j = 0; j < 10000; j++) {
order();
}
}
}.start();
}
try {
Thread.sleep(3000);//等待让线程跑完
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("库存量: " + orderNum);
}
}
优点:可以自己定义锁里面的功能
注意:必须和tyr...catch..联合使用
Lock lock = new ReentrantLock();//jdk1.5开始才有这种锁
public void order() {
lock.lock();//加锁 加锁和解锁都是自己很明显的写出来的,所以也叫做显式锁
try {
orderNum--; //可以抛出异常代码
} finally {//标准的规范的lock锁的加锁和解锁的写法
lock.unlock();//解锁
}