上一次接触了关键字synchronized,虽然能够使线程同步且不出现脏读的情况,但是它在某些情况下还是有弊端的,如果A线程调用同步方法执行一个长时间的任务,那么B线程则必须等待比较长的时间。这样子就是造成程序执行效率低下。那么该如何使用关键字synchronized呢。在synchronized块中就是同步执行,不在的话就是异步执行。没错,那么我们把它弄成一半异步,一半同步,这样子既能提高程序执行效率又能不出现脏读。
public class Task
{
public void dolongTimeTask()
{
for(int i=0;i<100;i++)
{
System.out.println("nosynchronized threadName="+Thread.currentThread().getName()+" i="+(i+1));
}
System.out.println("");
synchronized (this)
{
for(int i=0;i<100;i++)
{
System.out.println("synchronized threadName="+Thread.currentThread().getName()+" i="+(i+1));
}
}
}
}
public static void main(String[] args)
{
Task t=new Task();
ThreadA ta=new ThreadA(t);
ta.start();
ThreadB tb=new ThreadB(t);
tb.start();
}
在使用同步synchronized(this)代码块时需要注意,当一个线程访问object的一个synchronized (this)同步代码块时,其他线程对同一个object中所有其他synchronized(this)同步代码块的访问将会被阻塞,这说明synchronized 使用的“对象监视器”是一个。
多个线程调用同一个对象中的不同名称的synchronized 同步方法或者synchronized(this)代码块时,调用的效果就是按顺序执行,也就是同步的,阻塞的。
(1)synchronized同步方法
1)对其他synchronized 同步方法或synchronized (this)同步块调用呈阻塞作用
2)同一时间只有一个线程可以执行synchronized同步方法中的代码
(1)synchronized(this)同步代码块
1)对其他synchronized 同步方法或synchronized (this)同步块调用呈阻塞作用
2)同一时间只有一个线程可以执行synchronized(this)同步方法中的代码
还有一点,如果对象监视器不是同一个的话那么结果就是异步调用了,就会交叉运行。
public class Service
{
public void Test()
{
try
{
String anything=new String();
synchronized (anything)
{
System.out.println("线程的名称:"+Thread.currentThread().getName()+"在 "+System.currentTimeMillis()+"进入同步块");
Thread.sleep(3000);
System.out.println("线程的名称:"+Thread.currentThread().getName()+"在 "+System.currentTimeMillis()+"离开同步块");
}
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args)
{
Service s=new Service();
ThreadA ta=new ThreadA(s);
ta.setName("A");
ta.start();
ThreadB tb=new ThreadB(s);
tb.setName("B");
tb.start();
}
}
synchronized(非this对象x)格式的写法是将x对象本身作为"对象监视器",这样子可以得出:
1.当多个线程同时执行synchronized(x){}同步代码块时呈同步效果
2.当其他线程执行x对象中的synchronized同步方法呈同步效果
3.当其他线程执行x对象里面的synchronized(this)代码块时也呈同步效果。
这里举出第二个结论的例子:
public class MyObject
{
synchronized public void testMyObjectMethod()
{
System.out.println("testMyObjectMethod getlock time="+System.currentTimeMillis()+"run threadName="+Thread.currentThread().getName());
System.out.println("---------------");
System.out.println("testMyObjectMethod releaselock time="+System.currentTimeMillis()+"run threadName="+Thread.currentThread().getName());
}
}
public void testMethod1(MyObject myobject)
{
synchronized (myobject)
{
try
{
System.out.println("testMethod1 getlock time="+System.currentTimeMillis()+"run threadName="+Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println("testMethod1 releaseLock time="+System.currentTimeMillis()+"run threadName="+Thread.currentThread().getName());
}
catch(InterruptedException e)
{
}
}
}
public class ThreadA extends Thread
{
private Service s;
private MyObject m;
public ThreadA(Service s,MyObject m)
{
this.s=s;
this.m=m;
}
public void run()
{
s.testMethod1(m);
}
}
public class ThreadB extends Thread
{
private MyObject m;
public ThreadB(MyObject m)
{
this.m=m;
}
public void run()
{
m.testMyObjectMethod();
}
}
public class Run {
public static void main(String[] args)
{
Service s=new Service();
MyObject m=new MyObject();
ThreadA ta=new ThreadA(s,m);
ta.setName("a");
ta.start();
ThreadB tb=new ThreadB(m);
tb.setName("b");
tb.start();
}
}
网友评论