(一)同步方法
1、静态方法同步——测试
TestModel.java
public class TestModel
{
public static void function1()//方法1
{
try
{
Thread.sleep(5000);//延迟5s
}
catch (InterruptedException e)
{
}
System.out.println("in function----1");//打出日志
}
public static void function2()//方法2
{
try
{
Thread.sleep(5000);//延迟5s
}
catch (InterruptedException e)
{
}
System.out.println("in function----2");//打出日志
}
public static void function3()//方法3
{
try
{
Thread.sleep(5000);//延迟5s
}
catch (InterruptedException e)
{
}
System.out.println("in function----3");//打出日志
}
}
TestMain.java
public class TestMain
{
public static void main(String[] args)
{
new Run1().start();//启动线程1
new Run2().start();//启动线程2
new Run3().start();//启动线程3
}
static class Run1 extends Thread//线程1
{
@Override
public void run()
{
TestModel.function1();//调用TestModel静态同步方法1
}
}
static class Run2 extends Thread//线程2
{
@Override
public void run()
{
TestModel.function2();//调用TestModel静态同步方法2
}
}
static class Run3 extends Thread//线程3
{
@Override
public void run()
{
TestModel.function3();//调用TestModel静态同步方法3
}
}
}
测试结果:
静态方法的同步,就是用类本身(TestModel.class)作为锁,当class被某个静态同步方法锁定的时候,其他静态同步方法也想使用该class达到同步的效果,只有等待。
2、非静态方法同步——测试
TestModel.java
public class TestModel
{
public synchronized void function1()//方法1
{
try
{
Thread.sleep(5000);//延迟5s
}
catch (InterruptedException e)
{
}
System.out.println("in function----1");//打出日志
}
public synchronized void function2()//方法2
{
try
{
Thread.sleep(5000);//延迟5s
}
catch (InterruptedException e)
{
}
System.out.println("in function----2");//打出日志
}
public synchronized void function3()//方法3
{
try
{
Thread.sleep(5000);//延迟5s
}
catch (InterruptedException e)
{
}
System.out.println("in function----3");//打出日志
}
}
TestMain.java
public class TestMain
{
static TestModel testModel;//使用同一个实例
public static void main(String[] args)
{
testModel = new TestModel();
new Run1().start();//启动线程1
new Run2().start();//启动线程2
new Run3().start();//启动线程3
}
static class Run1 extends Thread//线程1
{
@Override
public void run()
{
testModel.function1();//调用testModel非静态同步方法1
}
}
static class Run2 extends Thread//线程2
{
@Override
public void run()
{
testModel.function2();//调用testModel非静态同步方法2
}
}
static class Run3 extends Thread//线程3
{
@Override
public void run()
{
testModel.function3();//调用testModel非静态同步方法3
}
}
}
测试结果:
上面使用的是同一实例进行调用,如果使用不同的实例调用,测试结果如下:
TestModel.java
public class TestMain
{
static TestModel testModel1;//实例1
static TestModel testModel2;//实例2
static TestModel testModel3;//实例3
public static void main(String[] args)
{
testModel1 = new TestModel();
testModel2 = new TestModel();
testModel3 = new TestModel();
new Run1().start();//启动线程1
new Run2().start();//启动线程2
new Run3().start();//启动线程3
}
static class Run1 extends Thread//线程1
{
@Override
public void run()
{
testModel1.function1();//调用testModel1非静态同步方法1
}
}
static class Run2 extends Thread//线程2
{
@Override
public void run()
{
testModel2.function1();//调用testModel2非静态同步方法1
}
}
static class Run3 extends Thread//线程3
{
@Override
public void run()
{
testModel3.function1();//调用testModel3非静态同步方法1
}
}
}
测试结果:
非静态同步方法,用调用者作为同步锁(类的一个实例);
所以在同一实例在不同线程中调用不同的非静态同步方法时,出现了等待的情况;
当线程中使用不同的实例进行非静态同步方法调用时,由于锁定的对象不同,所以互不影响。
(二)同步方法块
同步方法块,锁定的对象并不固定,开发人员可根据自身业务需求进行使用不同的锁,这里只简述锁定对象实例的情况。
1、同步方法块——单例模式锁定
TestModel.java
public class TestModel
{
private static TestModel instance = new TestModel();
private TestModel()
{
}
public static TestModel getInstance()
{
return instance;//单例模式
}
public void function1()//方法1
{
synchronized(instance)//这里写成this,效果一样
{
try
{
Thread.sleep(5000);//延迟5s
}
catch (InterruptedException e)
{
}
System.out.println("in function----1");//打出日志
}
}
public void function2()//方法2
{
synchronized(instance)//这里写成this,效果一样
{
try
{
Thread.sleep(5000);//延迟5s
}
catch (InterruptedException e)
{
}
System.out.println("in function----2");//打出日志
}
}
public synchronized void function3()//方法3
{
synchronized(instance)//这里写成this,效果一样
{
try
{
Thread.sleep(5000);//延迟5s
}
catch (InterruptedException e)
{
}
System.out.println("in function----3");//打出日志
}
}
}
TestMain.java
public class TestMain
{
static TestModel testModel1;//同一单例
static TestModel testModel2;//同一单例
static TestModel testModel3;//同一单例
public static void main(String[] args)
{
testModel1 = TestModel.getInstance();
testModel2 = TestModel.getInstance();
testModel3 = TestModel.getInstance();
new Run1().start();//启动线程1
new Run2().start();//启动线程2
new Run3().start();//启动线程3
}
static class Run1 extends Thread//线程1
{
@Override
public void run()
{
testModel1.function1();//调用testModel1方法1
}
}
static class Run2 extends Thread//线程2
{
@Override
public void run()
{
testModel2.function2();//调用testModel2方法2
}
}
static class Run3 extends Thread//线程3
{
@Override
public void run()
{
testModel3.function3();//调用testModel3方法3
}
}
}
测试结果:
同步方法块使用单例作为锁的时候,效果等同于静态同步方法;因为单例模式下,意味着只有一把锁。
2、同步方法块——非单例模式锁定
TestModel.java
public class TestModel
{
public void function1()//方法1
{
synchronized(this)//效果等同于非静态同步方法
{
try
{
Thread.sleep(5000);//延迟5s
}
catch (InterruptedException e)
{
}
System.out.println("in function----1");//打出日志
}
}
public void function2()//方法2
{
synchronized(this)//效果等同于非静态同步方法
{
try
{
Thread.sleep(5000);//延迟5s
}
catch (InterruptedException e)
{
}
System.out.println("in function----2");//打出日志
}
}
public synchronized void function3()//方法3
{
synchronized(this)//效果等同于非静态同步方法
{
try
{
Thread.sleep(5000);//延迟5s
}
catch (InterruptedException e)
{
}
System.out.println("in function----3");//打出日志
}
}
}
TestMain.java
public class TestMain
{
static TestModel testModel1;//单例1
static TestModel testModel2;//单例2
static TestModel testModel3;//单例3
public static void main(String[] args)
{
testModel1 = new TestModel();
testModel2 = new TestModel();
testModel3 = new TestModel();
new Run1().start();//启动线程1
new Run2().start();//启动线程2
new Run3().start();//启动线程3
}
static class Run1 extends Thread//线程1
{
@Override
public void run()
{
testModel1.function1();//调用testModel1方法1
}
}
static class Run2 extends Thread//线程2
{
@Override
public void run()
{
testModel2.function2();//调用testModel2方法2
}
}
static class Run3 extends Thread//线程3
{
@Override
public void run()
{
testModel3.function3();//调用testModel3方法3
}
}
}
测试结果:
同步方法块使用非单例作为锁的时候,效果等同于非静态同步方法;锁定的对象为实际调用的实例。
现在修改TestMain.java如下:
TestModel.java
public class TestMain
{
static TestModel testModel1;//单例1
static TestModel testModel2;//引用1
static TestModel testModel3;//引用1
public static void main(String[] args)
{
testModel1 = new TestModel();
testModel2 = testModel1;
testModel3 = testModel1;
new Run1().start();//启动线程1
new Run2().start();//启动线程2
new Run3().start();//启动线程3
}
static class Run1 extends Thread//线程1
{
@Override
public void run()
{
testModel1.function1();//调用testModel1方法1
}
}
static class Run2 extends Thread//线程2
{
@Override
public void run()
{
testModel2.function2();//调用testModel2方法2
}
}
static class Run3 extends Thread//线程3
{
@Override
public void run()
{
testModel3.function3();//调用testModel3方法3
}
}
}
测试结果:
由于锁定的对象为同一个实例,出现了等待的现象。
三、总结
同步的出现是为了确保数据操作的正确性,而同步的核心即在于锁的合理使用,明白了锁的使用原理,同步自然也不成问题。