JAVA多线程初识(5)---synchronized和lock锁

synchronized一般用于同步处理中:
所谓的同步处理是所有的线程不是一起进入到方法中执行,而是按照顺序一个一个进来。
synchronized和lock锁相当于一把锁。
使用synchronized关键字处理有两种模式:同步代码块、同步方法
使用同步代码块 :
如果要使用同步代码块必须设置一个要锁定的对象,所以一般可以锁定当前对象:this
synchronized (this){ //this表示当前对象
//同步代码块,在方法中定义
}
同步方法:
//锁一个方法
public synchronized void sale(){

}

class Sync{
    public void test() {
        synchronized (this) {
            System.out.println("开始"+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("结束"+Thread.currentThread().getName());
        }
    }
}
class MyThread extends Thread{
    private Sync sync;
    public MyThread(Sync sync) {
        // TODO Auto-generated constructor stub
        this.sync = sync;
    }   
    @Override
    public void run() {
        // TODO Auto-generated method stub
    this.sync.test();           
    }   
}

public class Thread8 {
    public static void main(String[] args) {
        Sync sync = new Sync();
        for (int i = 0; i < 3; i++) {
            Thread thread = new MyThread(sync);
            thread.start();
        }
    }
}

这里写图片描述

上述代码以及运行结果,我们可以看到三个线程同时运行test()方法

实际上,synchronized(this)以及非static的synchronized方法,只能防止多个线程同时执行同一个对象的同步代码段。即synchronized锁住的是括号里的对象,而不是代码。对于非static的synchronized方法,锁的就是对象本身也就是this。

我们如果要锁住这段代码,有两种思路:

第一种,锁住同一个对象

第二种,锁住这个类对应的Class对象

class Sync {
    public void test() {
        synchronized (Sync.class) {
            System.out.println("test方法开始,当前线程为 " + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("test方法结束,当前线程为 " + Thread.currentThread().getName());
        }
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        Sync sync = new Sync();
        sync.test();
    }
}

public class Thread8 {
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            Thread thread = new MyThread();
            thread.start();
        }
    }
}

上面代码用synchronized(Sync.class)实现了全局锁的效果。因此,如果要想锁的是代码段,锁住多个对象的同一方法,使用这种全局锁,锁的是类而不是this。
static synchronized方法,static方法可以直接类名加方法名调用方法中无法使用this,所以它锁的不是this,而是类的Class对象,所以,static synchronized方法也相当于全局锁,相当于锁住了代码段。

Lock锁:

Lock锁机制是JDK 5之后新增的锁机制,不同于内置锁,Lock锁必须显式声明,并在合适的位置释放锁。Lock是一个接口,其由三个具体的实现:ReentrantLock、ReetrantReadWriteLock.ReadLock 和 ReetrantReadWriteLock.WriteLock,即重入锁、读锁和写锁。

在了解lock锁之前我们需要了解一个重入锁,ReentrantLock
对于我们之前的synchronized而言,锁的对象实现了原子性,但是如果其他的线程出现饥饿问题的话,我们就需要用ReentrantLock来中断自己。
即:synchronized可能产生死锁,ReentranceLock可以中断死锁。

lock锁和synchronize区别:
Lock接口可以尝试非阻塞地获取锁 当前线程尝试获取锁。如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁。
*Lock接口能被中断地获取锁 与synchronized不同,获取到锁的线程能够响应中断,当获取到的锁的线程被中断时,中断异常将会被抛出,同时锁会被释放。
Lock接口在指定的截止时间之前获取锁,如果截止时间到了依旧无法获取锁,则返回。

阅读更多
版权声明: https://blog.csdn.net/Devil_Net/article/details/80338014
文章标签: 线程 java
个人分类: java
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭