1.同步监视器和共享数据的理解,以及注意点。
1.当涉及到多个线程、共享数据时需要考虑线程安全问题,
2.同步监视器相当于一把锁,当一个线程操作共享数据时,该线程上锁,其他线程只能先等着,这样就避免了例如多窗口抢票时产生的重票和错票问题。
注意:在设计同步代码块的嵌套时易产生死锁问题,线程一拿着锁A准备拿锁B,线程二拿着锁B准备拿锁A,二者僵持,程序不终止,就这样一直等下去,类似于死循环
3.因此在使用同步代码块时要小心
/*
线程一拿到了锁s1 睡眠
同时(极有可能)线程二拿到了锁s2 睡眠
线程一 就绪 准备拿锁s2 线程二 就绪 准备拿锁s1 二者僵持发生死锁问题 程序不抛出异常一直是执行状态
*/
public class DeadLockTest {
public static void main(String[] args) {
StringBuffer s1=new StringBuffer();
StringBuffer s2=new StringBuffer();
new Thread(){//线程一
@Override
public void run() {
synchronized (s1) {
s1.append("a");
s2.append("1");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s2) {
s1.append("b");
s2.append("2");
System.out.println(s1);
System.out.println(s2);
}
}
}
}.start();
new Thread(new Runnable() {//线程二
@Override
public void run() {
synchronized (s2) {
s1.append("c");
s2.append("3");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s1) {
s1.append("d");
s2.append("4");
System.out.println(s1);
System.out.println(s2);
}
}
}
}).start();
}
}
2.sleep()和wait()的区别
同:二者都可以是线程进入阻塞状态
异:sleep()并不释放锁 wait()释放锁
3.线程生命周期的转换
4.单例模式(线程安全)写法
//线程不安全的:多个线程由于阻塞的原因可能创建了多个对象
/*class Bank {
private Bank() {
}
private static Bank instance = null;
public static Bank getInstance() {
if (instance == null) {
instance = new Bank();
}
return instance;
}
}*/
class Bank {
private Bank() {
}
private static Bank instance = null;
//方式一:
/*public static synchronized Bank getInstance() {//函数体中存在共用的对象
if (instance == null) {
instance = new Bank();
}
return instance;
}*/
//方式二:效率更高
public static Bank getInstance() {//函数体中存在共用的对象
if (instance == null) {//只有当实例对象为空时才进行同步化操作
synchronized (Bank.class){
instance = new Bank();
}
}
return instance;
}
}