0
点赞
收藏
分享

微信扫一扫

关于synchronized


如果用synchronized修饰一个类成员方法A,那么就不会出现下面的情况:
同时多个线程访问这个类的A方法。
当然如果还有一个方法B,它没有被synchronized修饰,那么A方法与B方法是可以并行执行的。如下:

package thread;

public class SyncTest implements Runnable {

public synchronized void m1() throws Exception{
System.out.println("m1开始");
Thread.sleep(2000);
System.out.println("m1结束");
}

public void m2() throws Exception {
System.out.println("m2开始");
Thread.sleep(2000);
System.out.println("m2结束");
}

public void run() {
try {
m1();
} catch(Exception e) {
e.printStackTrace();
}
}

public static void main(String[] args) throws Exception {
SyncTest tt = new SyncTest();
Thread t = new Thread(tt);
t.start();

Thread.sleep(1000); //保证先运行m1
tt.m2();
}
}

大家可以先猜一下运行结果


m1先运行打印出


m1开始


然后睡觉(2s后醒来)


过了大概1s


tt.m2()运行了


打印出


m2开始


再等一会


m1结束


m2结束


运行的结果也确实是


m1开始


m2开始


m1结束


m2结束


我们得出一个结论


成员函数A使用synchronized修饰,并不会影响没有使用synchronized修饰的方法B。



不过如果给m2也加上synchronized,会怎么呢?


结果如下


m1开始


m1结束


m2开始


m2结束



恩?答案是的。即使我们m1休眠的时间再长,m2也不会在m1执行结束之前启动。


因而我们得出结论


如果一个类中多个成员函数都用synchronized修饰,那么即使在多线程下,这些函数也不能同时被调用。



上面说的所以函数都是成员函数,如果把synchronized加到static方法上呢?


大家都知道,static的方法属于类方法,它属于这个Class(注意:这里的Class不是指Class的某个具体对象),那么static获取到的锁,就是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。而非static方法获取到的锁,就是当前调用这个方法的对象的锁了。所以,他们之间不会产生互斥。


看下面的例子


/**
* @author Jack Zhang
* @version vb1.0
* @Email virgoboy2004@163.com
* @Date 2012-5-20
*/
public class Test
{
public static synchronized void staticX() throws InterruptedException
{
for (int i = 0; i < 10; i++){
Thread.sleep(1000);
System.out.println("staticX.......................");
}
}

public synchronized void x() throws InterruptedException{
for (int i = 0; i < 10; i++){
Thread.sleep(1000);
System.out.println("x.......................");
}
}

public static void main(String[] args)
{
final Test test1 = new Test();
Thread thread = new Thread(new Runnable(){
public void run(){
try{
test1.x();
}catch (InterruptedException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "a");

Thread thread1 = new Thread(new Runnable(){
public void run(){
try{
Test.staticX();
} catch (InterruptedException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "b");

thread1.start();
thread.start();
}
}



结果是


staticX.......................


x.......................


x.......................


staticX.......................


staticX.......................


x.......................


x.......................


staticX.......................


x.......................


staticX.......................


staticX.......................


x.......................


x.......................


staticX.......................


x.......................


staticX.......................


x.......................


staticX.......................


x.......................


staticX.......................


一个锁加到的类上,另一个锁加到了对象上。是两回事。



那当我们想让所有这个类下面的对象都同步的时候,也就是让所有这个类下面的对象共用同一把锁的时候,我们如何办呢?



看代码:


/**
* @author Jack Zhang
* @version vb1.0
* @Email virgoboy2004@163.com
* @Date 2012-5-20
*/
public class Test
{
public final static Byte[] locks = new Byte[0];

public static void staticX() throws InterruptedException
{
synchronized (locks)
{
for (int i = 0; i < 10; i++)
{
Thread.sleep(1000);
System.out.println("staticX.......................");
}
}
}

public void x() throws InterruptedException
{
synchronized (locks)
{
for (int i = 0; i < 10; i++)
{
Thread.sleep(1000);
System.out.println("x.......................");
}
}
}

public static void main(String[] args)
{
final Test test1 = new Test();
final Test test2 = new Test();
Thread thread = new Thread(new Runnable()
{
public void run()
{
try
{
test1.x();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "a");

Thread thread1 = new Thread(new Runnable()
{
public void run()
{
try
{
Test.staticX();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "b");

thread1.start();
thread.start();
}
}

结果


staticX.......................


staticX.......................


staticX.......................


staticX.......................


staticX.......................


staticX.......................


staticX.......................


staticX.......................


staticX.......................


staticX.......................


x.......................


x.......................


x.......................


x.......................


x.......................


x.......................


x.......................


x.......................


x.......................


x.......................



关于synchronized(this)

我们知道在java中,this指的是调用这个方法的对象

如果我们写这样的锁synchronized(this) 会怎么样呢? 试一下不就知道了

public class Test
{
public final static Byte[] locks = new Byte[0];

public void staticX() throws InterruptedException
{
synchronized (this)
{
for (int i = 0; i < 10; i++)
{
Thread.sleep(1000);
System.out.println("staticX.......................");
}
}
}

public void x() throws InterruptedException
{
// synchronized (this)
{
for (int i = 0; i < 10; i++)
{
Thread.sleep(1000);
System.out.println("x.......................");
}
}
}

public static void main(String[] args)
{
final Test test1 = new Test();
// final Test test2 = new Test();
Thread thread = new Thread(new Runnable()
{
public void run()
{
try
{
test1.x();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "a");

Thread thread1 = new Thread(new Runnable()
{
public void run()
{
try
{
test1.staticX();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "b");

thread1.start();
thread.start();
}
}

此时x与staticx交替打印

这个大家能理解吗?x()方法没有任何锁,它自然能执行

如果我去掉x()方法里面的

//   synchronized (this)

这行的注释呢?

结果是先连续打印10个staticx然后再打印10个x





感谢glt


举报

相关推荐

0 条评论