synchronized关键字详解

Java中可以使用synchronized进行同步处理 ,难点就是使用synchronized关键字加锁时,锁的到底是哪些东西,本文将进行说明。

synchronized的使用场景:

   修饰方法(同步方法)

   修饰代码块(同步代码块)

接下来看代码实现:

public class Test{
    public static void main(String[] args) {
    final TestSynchronzed ts = new TestSynchronzed();
    Thread thread1 = new Thread(new Runnable() {
        public void run() {
            ts.method1(); //thread1调用method1()方法
        }
    });
    Thread thread2 = new Thread(new Runnable() {
        public void run() {
            ts.method2(); //Thread2调用method2()方法
        }
    });
        thread1.start();
        thread2.start();
    }
}
class TestSynchronzed {

    public void method1() {
        synchronized (this) {
            int i = 4;
            while (i-- > 0) {
                System.out.println(Thread.currentThread().getName() + "," + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public synchronized void method2() {
        int i = 5;
        while (i-- > 0) {
            System.out.println(Thread.currentThread().getName() + "," + i);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

输出结果:

从method1中synchronized(this)可以看出锁的是当前对象,而method2锁的也是当前对象。所以在上面代码中method1和method2锁的是同一个对象。所以当有一个线程进入method1执行的时候,其他线程被阻塞(既不能访问method1也不能访问method2),只有当对象锁被Thread-0释放后,Thread-1才能访问method2()方法。

如果去掉method2()的synchronized关键字,结果如下:

可以看出这时是交替执行的,原因是当某个线程得到了对象锁,但另一个线程仍然可以访问没有进行同步的代码或方法。上锁了的方法和普通没上锁的方法是互不影响的。 当某个线程获取到对象锁时,只能阻止其他线程获取同一个锁,并不能阻止其他线程访问没有加锁的方法。

上面提到的锁住的是对象,下面将谈到类锁:

public class Test{
    public static void main(String[] args) {
    final TestSynchronzed ts = new TestSynchronzed();
    Thread thread1 = new Thread(new Runnable() {
        public void run() {
            ts.method1();
        }
    });
    Thread thread2 = new Thread(new Runnable() {
        public void run() {
            ts.method2();
        }
    });
        thread1.start();
        thread2.start();
    }
}
class TestSynchronzed {

    public void method1() {
        synchronized (TestSynchronzed.class) {
            int i = 4;
            while (i-- > 0) {
                System.out.println(Thread.currentThread().getName() + "," + i);
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static synchronized void method2() {
        int i = 5;
        while (i-- > 0) {
            System.out.println(Thread.currentThread().getName() + "," + i);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

运行结果如下:

上面代码中method1锁的是该类的Class对象。众所周知类的Class对象是描述各个类的组成,一个类有且只有一个Class对象。锁住Class对象相当于锁住了该类的类对象。而method2方法是静态方法,锁住静态方法也相当于锁的是该类的类对象。所以程序运行时各个线程是有序的。

上面提到了类锁和对象锁,需要说明的是类锁和对象锁并不是同一类锁,验证如下:

public class Test{
    public static void main(String[] args) {
    final TestSynchronzed ts = new TestSynchronzed();
    Thread thread1 = new Thread(new Runnable() {
        public void run() {
            ts.method1();
        }
    });
    Thread thread2 = new Thread(new Runnable() {
        public void run() {
            ts.method2();
        }
    });
        thread1.start();
        thread2.start();
    }
}
class TestSynchronzed {

    public void method1() {
        synchronized (TestSynchronzed.class) {
            int i = 4;
            while (i-- > 0) {
                System.out.println(Thread.currentThread().getName() + "," + i);
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public synchronized void method2() {
        int i = 5;
        while (i-- > 0) {
            System.out.println(Thread.currentThread().getName() + "," + i);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

运行结果如下:

可见线程是交替的,说明类锁和对象锁并不是一类锁。

 

参考文章:https://www.cnblogs.com/wl0000-03/p/5973039.html 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值