上一篇博客写的是synchronized作用域,因为公司项目上的问题,发现了这些以前都没在意的坑。两个内容方便阅读分开写了。
我们项目上使用的是,单例模式的类,在非static方法上加了synchronized关键字。
非static方法加synchronized关键字,锁是类new的对象,因为是单例模式的,对象只有一个,所以是可以实现锁功能的。
emmm,理解上都是对的,但测试时候发现还是没锁住,就查了一下原因。好吧,原来单例模式写的不对,来看一下下面代码:
public class Test{
public static void main(String[] args) {
MyTest myTest1 = new MyTest("thread1");
Thread thread1 = new Thread(myTest1);
thread1.start();
MyTest myTest2 = new MyTest("thread2");
Thread thread2 = new Thread(myTest2);
thread2.start();
}
}
class MyTest implements Runnable{
String name;
MyTest(String name) {
this.name = name;
}
@Override
public void run() {
try {
LockTest.getInstance().houh(name);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class LockTest {
private LockTest() {}
private static LockTest lock = null;
public static LockTest getInstance(){
if(lock==null){
System.out.println("new 新对象");
lock= new LockTest();
}
return lock;
}
public synchronized void houh(String name) throws InterruptedException {
for(int i = 0; i < 100;i++) {
System.out.println(name +" "+ i);
}
}
}
控制台显示new了两个对象,并且程序没锁住,线程是交叉执行的。
重点来了,单例模式的写法不应该像上边这样写,虽然网上很多这么写的,但实际是错的达不到单例的效果的。
单例getInstance需要是同步的,需要加synchronized关键字。
class LockTest {
private LockTest() {}
private static LockTest lock = null;
public static synchronized LockTest getInstance(){
if(lock==null){
System.out.println("new 新对象");
lock= new LockTest();
}
return lock;
}
public synchronized void houh(String name) throws InterruptedException {
for(int i = 0; i < 100;i++) {
System.out.println(name +" "+ i);
}
}
}
程序再执行一次
两个线程调用这个类的方法,只new了一次对象。并且达到了一个线程全部执行完另一个线程再执行的效果,加锁成功。