如下:

惰性代码,存程安全性问题,因为当多个线程创建一个单例时多线程避免死锁,可能会重复创建它来解决惰性线程安全性. 通常有两种方法
此代码,在首次创建实例时,其他线程必须判断锁,性能相对较低.
class Bank1 {
private Bank1() {
}
private static Bank1 instance = null;
//这种写法,效率较低,因为第一次已经将instance创建出来了,其他线程再去用的时候,还得去再判断一下锁,效率比较低
public static Bank1 getInstance() {
synchronized (Bank1.class) {
if (instance == null) {
return new Bank1();
}
return instance;
}
}
}
双重判断,当第一个线程创建实例对象时,第二个线程看到他不为NULL,因此他无需再次判断锁.
class Bank2 {
private Bank2() {
}
private static Bank2 instance = null;
//这种写法,做了双重判断,当第一个线程创建了实例对象之后,第二个线程看到他不是NULL 了,就不用去再次判断锁了
public static Bank2 getInstance() {
if (instance == null) {
synchronized (Bank2.class) {
if (instance == null) {
return new Bank2();
}
}
}
return instance;
}
}
什么是僵局?
例如:
两个人有两双筷子,但他们握着对方的筷子,他们在等对方吃饭之前先等对方给他们筷子. 此时,两个人被冻结,没有人可以吃. 就像死锁问题一样.
以下代码演示了死锁
以下代码使用双锁. 第一个线程捕获s1,然后捕获s2,第二个线程捕获s2,然后捕获s1.
线程1进入睡眠状态时,它将挂起一段时间. 这时,线程2在运行之后仅抓住s2的锁,因为s2也有睡眠,然后线程1想要获取s2. 此时,出现了僵局.
public class DeadLockTest {
//死锁问题
//产生死锁的原因,sleep之后,死锁概率加大,两个锁互相等待对方释放锁,而又拿着对方的锁不放,就导致死锁
public static void main(String[] args) {
StringBuilder s1 = new StringBuilder();
StringBuilder s2 = new StringBuilder();
//使用继承方式创建线程
new Thread() {
@Override
public void run() {
synchronized (s1) {
s1.append("a");
s2.append("1");
sleepTime(100);
synchronized (s2) {
s1.append("b");
s2.append("2");
System.out.println(s1);
System.out.println(s2);
}
}
}
}.start();
//使用实现Runnable 接口的方式创建线程
new Thread(new Runnable() {
@Override
public void run() {
synchronized (s2) {
s1.append("c");
s2.append("3");
sleepTime(100);
synchronized (s1) {
s1.append("d");
s2.append("4");
System.out.println(s1);
System.out.println(s2);
}
}
}
}).start();
}
private static void sleepTime(int time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
如何避免死锁?
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-268830-2.html
但是网站不停改收益的条件也是显而易见的