synchronized同步代码块任意锁

/ 多线程 / 没有评论 / 289浏览

我们知道synchronized同步代码块要传入一个参数,这个参数也就是synchronized同步代码块的锁。在上一篇中我们用this也就是当前对象来当synchronized同步代码块的锁,接下来我们随便创建一个任意的对象,来当synchronized同步代码块锁。

/**
* 商品信息
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-13 11:51
* @since 1.0.0
*/
public class Goods extends Thread {

/**
* 商品库存
*/
private int stock = 5;

private String lock = new String();

@Override
public void run() {
synchronized (lock) {
stock--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(String.format("购买用户: %s 当前库存: %s", Thread.currentThread().getName(), stock));
}
}
}
/**
* 用户购买
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-13 11:57
* @since 1.0.0
*/
public class GookdsTest {
public static void main(String[] args) throws InterruptedException {
Goods goods = new Goods();
Thread ming = new Thread(goods, "小明");
Thread hong = new Thread(goods, "小红");
ming.start();
hong.start();
}
}
购买用户: 小明 当前库存: 4
购买用户: 小红 当前库存: 3

我们创建了一个实例变量的字符串对象来当synchronized同步代码块的锁,看输出没有任何问题,依然是线程安全的。可见我们创建任意对象来当锁都是允许的。但这里有一点要特别注意,必须保证每一个线程所获得的锁是同一个,因为synchronized同步代码块就是靠锁来保证线程安全的,如果多个线程获取的锁不是同一个,那么即使我们使用了synchronized同步代码块也还是会有线程安全问题的。原因就是虽然线程一获取到了锁,但线程二依然可以获取到锁,原因就是因为它们不是同一个锁,这时它们都可以访问synchronized同步代码块里的内容,所以依然会造成线程安全问题。下面的代码来演示用不同的锁产生的线程安全问题。

/**
* 商品信息
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-13 11:51
* @since 1.0.0
*/
public class Goods extends Thread {

/**
* 商品库存
*/
private int stock = 5;

@Override
public void run() {
String lock = new String();
synchronized (lock) {
stock--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(String.format("购买用户: %s 当前库存: %s", Thread.currentThread().getName(), stock));
}
}
}
购买用户: 小红 当前库存: 3
购买用户: 小明 当前库存: 3