首页 > 代码库 > 关于synchronized

关于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.......................



参考资料
http://blog.csdn.net/virgoboy2004/article/details/7585182

关于synchronized