笔记————synchornized

synchornized关键字的几种用法如下:

1、作用在方法上,锁是当前实例对象

  • 不同线程对于同一个对象的锁具有互斥性

当A线程获取到锁之后,B线程只能等A线程释放锁之后才能获取

package com.piao.thread1;

public class test_sync_method {
    public static void main(String[] args) {
        sync_method method1 = new sync_method();
        Thread thread1 = new Thread(method1);
        Thread thread2 = new Thread(method1);
        thread1.start();
        thread2.start();
    }
}
class sync_method implements Runnable{
    public synchronized void f(){
        System.out.println("f() start by: "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            System.out.println("f() end by: "+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        f();

    }
}
输出:
f() start by: Thread-0
f() end by: Thread-0
f() start by: Thread-1
f() end by: Thread-1

上面这个例子中,因为两个线程是共用一把锁,因此线程2只能等线程1执行结束之后才能运行

  • 不同线程对于不同对象相当于异步

synchornized获得的是对象锁,如果有多个对象,jvm就会创建多个锁

package com.piao.thread1;


public class test_sync_method {
    public static void main(String[] args) {
        sync_method method1 = new sync_method();
        sync_method method2 = new sync_method();
        Thread thread1 = new Thread(method2);
        Thread thread2 = new Thread(method1);
        thread1.start();
        thread2.start();
    }
}
class sync_method implements Runnable{
    public synchronized void f(){
        System.out.println("f() start by: "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            System.out.println("f() end by: "+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        f();

    }
}
输出:
f() start by: Thread-0
f() start by: Thread-1
f() end by: Thread-1
f() end by: Thread-0

上面这个例子中,因为两个线程填入的实例不一样,表示两个线程的锁是不一样的,因此说明线程2不需要等线程1执行完毕,就可以执行该实例中的同名方法

  • 所有对象都自动含有单一的锁

当对象在调用其任意synchornized方法时,此对象都会被加锁,这时该对象上的其他synchornized方法只有等到前一个方法调用完毕并释放锁之后才能被调用。

package com.piao.thread1;


public class test_sync_method {
    public static void main(String[] args) {
        sync_method method1 = new sync_method();
        Thread thread1 = new Thread(method1);
        Thread thread2 = new Thread(method1);
        thread1.start();
        thread2.start();
    }
}
class sync_method implements Runnable{
    private static int count=1;
    public synchronized void f(){
        System.out.println("f() start by: "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            System.out.println("f() end by: "+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public synchronized void g(){
        System.out.println("g() start by: "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            System.out.println("g() end by: "+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
       if (count==1){
           count=2;
           f();
       }else{
           count=1;
           g();
       }

    }
}
输出:
f() start by: Thread-0
f() end by: Thread-0
g() start by: Thread-1
g() end by: Thread-1
  • 一个任务可以多次获得对象的锁

如果一个方法在同一个对象上调用第二个方法,后者又调用了同一个对象上的另一个方法,就会发生这种情况。jvm负责跟踪对象加锁的次数。如果一个对象被解锁(即完全释放锁),计数器就会变为0;在任务第一次给对象加锁时,计数器变为1.每当这个相同的任务在这个对象上获取锁时,计数器都会递增。显然只有首先获得锁的任务才能被允许继续加锁。每当任务离开一个synchornized方法,计数器递减,当计数器为0时,释放锁,此时,别的任务就可以获得此资源。

package com.piao.thread1;


public class test_sync_method {
    public static void main(String[] args) {
        sync_method method1 = new sync_method();
        Thread thread1 = new Thread(method1);
        Thread thread2 = new Thread(method1);
        thread1.start();
        thread2.start();
    }
}
class sync_method implements Runnable{
    private static int count=1;
    public synchronized void f(){
        System.out.println("f() start by: "+Thread.currentThread().getName());
        try {
            g();
            Thread.sleep(1000);
            System.out.println("f() end by: "+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public synchronized void g(){
        System.out.println("g() start by: "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            System.out.println("g() end by: "+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
       if (count==1){
           count=2;
           f();
       }else{
           count=1;
           g();
       }

    }
}
输出:
f() start by: Thread-0
g() start by: Thread-0
g() end by: Thread-0
f() end by: Thread-0
g() start by: Thread-1
g() end by: Thread-1
  • 同步不能继承
package com.piao.thread1;


public class test_sync_method {
    public static void main(String[] args) {
        sync_method method1 = new sync_method();
        sync_method method2 = new sync_method();
        sync_method1 sync_method1 = new sync_method1();
        Thread thread1 = new Thread(sync_method1);
        Thread thread2 = new Thread(sync_method1);
        thread1.start();
        thread2.start();
    }
}
class sync_method implements Runnable{
    private static int count=1;
    public synchronized void f(){
        System.out.println("f() start by: "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            System.out.println("f() end by: "+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public synchronized void g(){
        System.out.println("g() start by: "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            System.out.println("g() end by: "+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
       if (count==1){
           count=2;
           f();
       }else{
           count=1;
           g();
       }

    }
}
class sync_method1 extends sync_method{
    public void f(){
        System.out.println("s() start by: "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            System.out.println("s() end by: "+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        super.f();
    }

    @Override
    public void run() {
        f();
    }
}
输出:
s() start by: Thread-0
s() start by: Thread-1
s() end by: Thread-0
s() end by: Thread-1
f() start by: Thread-0
f() end by: Thread-0
f() start by: Thread-1
f() end by: Thread-1

不难发现,两个线程进入子类几乎是一起进入的。

  • 父类和子类是同一个锁
package com.piao.thread1;


public class test_sync_method {
    public static void main(String[] args) {
        sync_method1 sync_method1 = new sync_method1();
        Thread thread1 = new Thread(sync_method1);
        Thread thread2 = new Thread(sync_method1);
        thread1.start();
        thread2.start();
    }
}
class sync_method implements Runnable{
    private static int count=1;
    public synchronized void f(){
        System.out.println("f() start by: "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            System.out.println("f() end by: "+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public synchronized void g(){
        System.out.println("g() start by: "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            System.out.println("g() end by: "+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
       if (count==1){
           count=2;
           f();
       }else{
           count=1;
           g();
       }

    }
}
class sync_method1 extends sync_method{
    public synchronized void f(){
        System.out.println("s() start by: "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            System.out.println("s() end by: "+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        super.f();
    }

    @Override
    public void run() {
        f();
    }
}
输出:
s() start by: Thread-0
s() end by: Thread-0
f() start by: Thread-0
f() end by: Thread-0
s() start by: Thread-1
s() end by: Thread-1
f() start by: Thread-1
f() end by: Thread-1

可以发现,只有当一个线程释放锁之后。另一个线程才能获得资源

2、作用在方法块上,锁就是括号里的对象

  • 不同线程对于不同对象,相当于异步
package com.piao.thread1;


public class test_sync_method {
    public static void main(String[] args) {
        sync_method method1 = new sync_method();
        sync_method method = new sync_method();
        Thread thread1 = new Thread(method);
        Thread thread2 = new Thread(method1);
        thread1.start();
        thread2.start();
    }
}
class sync_method implements Runnable{
    private static int count=1;
    private  sync_method1 method1=new sync_method1();
    @Override
    public void run() {
       method1.f();

    }
}
class sync_method1{
    public void f(){
        synchronized (this){
            System.out.println("s() start by: "+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
                System.out.println("s() end by: "+Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


}
输出:
s() start by: Thread-0
s() start by: Thread-1
s() end by: Thread-0
s() end by: Thread-1
  • 当锁是类对象时
package com.piao.thread1;


public class test_sync_method {
    public static void main(String[] args) {
        sync_method method1 = new sync_method();
        sync_method method = new sync_method();
        Thread thread1 = new Thread(method);
        Thread thread2 = new Thread(method1);
        thread1.start();
        thread2.start();
    }
}
class sync_method implements Runnable{
    private static int count=1;
    private  sync_method1 method1=new sync_method1();
    @Override
    public void run() {
       method1.f();

    }
}
class sync_method1{
    public void f(){
        synchronized (sync_method1.class){
            System.out.println("s() start by: "+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
                System.out.println("s() end by: "+Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


}
s() start by: Thread-0
s() end by: Thread-0
s() start by: Thread-1
s() end by: Thread-1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值