synchronized 总结-LMLPHP

方法锁形式: synchronized 修饰普通方法, 锁对象默认为 this ,也就是当前实例对象

注意如果是 不同 类锁的 不同 的同步代码块。情况是有点特殊的,虽然也是有顺序了。

package com.my.com.my.sysnc;

/**
 * 同步锁测试
 */
public class TestSynchronized implements  Runnable{

    static  TestSynchronized instance=new TestSynchronized();

    Object lock1=new Object();
    Object lock2=new Object();

    @Override
    public void run() {



        synchronized (lock1){
            System.out.println("lock1对象锁代码块,线程名"+Thread.currentThread().getName());

            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName()+"结束lock1");
        }

        synchronized (lock2){
            System.out.println("lock2对象锁代码块,线程名"+Thread.currentThread().getName());

            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName()+"结束lock2");
        }



    }




    public static void main(String[] args) {

        Thread thread1=new Thread(instance);
        Thread thread2=new Thread(instance);
        thread1.start();
        thread2.start();

    }

}



结果  即 ,在run 方法里面, 当 第一个线程执行完 第一个同步代码块的时候,在开始执行第一个代码块的时候。
此时 第二个线程会去执行第一个同步代码块。 这样就有 点并行执行了
:

lock1对象锁代码块,线程名Thread-0
Thread-0结束lock1
lock2对象锁代码块,线程名Thread-0
lock1对象锁代码块,线程名Thread-1
Thread-0结束lock2
Thread-1结束lock1
lock2对象锁代码块,线程名Thread-1
Thread-1结束lock2



类锁

synchronized 总结-LMLPHP

synchronized 总结-LMLPHP

如果是对象锁的话,那么不同的对象对于不同的线程来说,就不会起到 锁的作用了。

如果是 类锁的话,那么就可以做到 不同的对象对于不同的线程 起到 锁的作用。

普通方法: 即非 静态方法

抛出异常的适合, LOCK 锁不会释放锁,而 synchronized  会释放锁

面试题

1. 两个线程同时访问一个对象的同步方法:

能够锁住,同一个实例

2. 两个线程访问的是两个对象的同步方法。

因为不同的实例所有并没有锁的作用,锁对象不是同一个

3. 两个线程访问的是 synchronized 的静态方法

锁的是 class对象, 锁住 

4. 同时访问同步方法与非同步方法

同步方法不能影响 非同步方法。 

同步方法与非同步方法可以同时运行

5. 访问同一个对象的不同的普通同步方法

方法不能同时的运行。 锁的是同一个对象。受锁的影响

例子:

package com.my.com.my.sysnc;

/**
 * 同步锁测试
 */
public class TestSynchronized implements  Runnable{

    static  TestSynchronized instance=new TestSynchronized();

    @Override
    public void run() {

       if (Thread.currentThread().getName().equals("Thread-0")){
           test1();
       }else{
           test2();
       }


    }

    public  synchronized void test1(){
        System.out.println("对象锁代码块"+Thread.currentThread().getName());

        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"结束线程");
    }

    public  synchronized void test2(){
        System.out.println("对象锁代码块"+Thread.currentThread().getName());

        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"结束线程");
    }


    public static void main(String[] args) {

        Thread thread1=new Thread(instance);
        Thread thread2=new Thread(instance);
        thread1.start();
        thread2.start();

    }

}

 锁的是同一个实例,竞争的是同一个实例,所以受到影响

可能的结果 :
对象锁代码块Thread-1
Thread-1结束线程
对象锁代码块Thread-0
Thread-0结束线程




6. 同时访问静态 synchronized 和 非静态 synchronized 方法

锁不其作用,两个方法都可以一起运行。

因为静态锁的是 class 对象,非静态的 锁的是 实例对象。是不一样的

package com.my.com.my.sysnc;

/**
 * 同步锁测试
 */
public class TestSynchronized implements  Runnable{

    static  TestSynchronized instance=new TestSynchronized();

    Object lock1=new Object();
    Object lock2=new Object();

    @Override
    public void run() {

       if (Thread.currentThread().getName().equals("Thread-0")){
           test1();
       }else{
           test2();
       }




    }

    public static   synchronized void test1(){
        System.out.println("静态加锁方法1,,对象锁代码块"+Thread.currentThread().getName());

        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"结束线程");
    }

    public  synchronized void test2(){
        System.out.println("非静态加锁方法2,对象锁代码块"+Thread.currentThread().getName());

        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"结束线程");
    }


    public static void main(String[] args) {

        Thread thread1=new Thread(instance);
        Thread thread2=new Thread(instance);
        thread1.start();
        thread2.start();

    }

}

结果:
非静态加锁方法2,对象锁代码块Thread-1
静态加锁方法1,,对象锁代码块Thread-0
Thread-0结束线程
Thread-1结束线程



7. 方法抛异常后,会释放锁

package com.my.com.my.sysnc;

/**
 * 同步锁测试
 */
public class TestSynchronized implements  Runnable{

    static  TestSynchronized instance=new TestSynchronized();

    Object lock1=new Object();
    Object lock2=new Object();

    @Override
    public void run() {

       if (Thread.currentThread().getName().equals("Thread-0")){
           test1();
       }else{
           test2();
       }




    }

    public    synchronized void test1(){
        System.out.println("对象锁代码块"+Thread.currentThread().getName());

        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    // 抛出异常后,释放锁,由JVM处理释放锁
       throw  new RuntimeException("抛出异常");
    }

    public  synchronized void test2(){
        System.out.println("对象锁代码块"+Thread.currentThread().getName());

        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"结束线程");
    }


    public static void main(String[] args) {

        Thread thread1=new Thread(instance);
        Thread thread2=new Thread(instance);
        thread1.start();
        thread2.start();

    }

}


结果:
对象锁代码块Thread-0
对象锁代码块Thread-1
Exception in thread "Thread-0" java.lang.RuntimeException: 抛出异常
	at com.my.com.my.sysnc.TestSynchronized.test1(TestSynchronized.java:36)
	at com.my.com.my.sysnc.TestSynchronized.run(TestSynchronized.java:17)
	at java.lang.Thread.run(Thread.java:748)
Thread-1结束线程


synchronized 总结-LMLPHP



性质

1, 可重入:避免死锁,提升封装性

指的是 同一线程的外层函数获得锁之后,内层函数可以之间再次获取该锁

同一个方法可重入(比如递归调用),

不要求同一个方法也可以重入(比如同一个类中调用2个都是锁的方法) ,

可重入不要求 是同一个类中的(子类的 重写父类的加锁方法,并调用父类的加锁方法)

2,不可中断 

synchronized 总结-LMLPHP

3. 粒度

线程而非调用

以上来自慕课网

07-15 04:56