synchronized和ReentrantLock

synchronized 锁住的是对象和类(锁住类和对象有什么区别???),而不是代码。类的每个对象都有一个监视器锁(monitor),当monitor被占用时就会处于锁定状态。

synchronized(锁的对象)可以保证方法或代码块在运行时,同一时刻只有一个线程可以进入到临界区(互斥性),同时它还保证了共享变量的内存可见性。

  • 普通同步方法,锁是当前实例对象。 * 静态同步方法,锁是当前类的class对象。 * 同步代码块,锁是括号中的对象。
  • 如果Synchronized(类名.class){}.
package com.thread.sync;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author zsw
 * @date 2021/1/21 13:41
 * @description : synchronized  锁住的是对象和类,而不是代码。类的每个对象都有一个监视器锁(monitor),当monitor被占用时就会处于锁定状态。
 */
@Slf4j
public class SyncCla {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool(); // 创建一个线程池
        for (int i = 0; i < 10; i++) {
            // 开启10个行程
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    testCla testCla = new testCla();
                    testCla.testSync();  // 结果打印了全部的锁的是SynCla对象 ,再打印结束:{},说明synchronizeds锁的是对象
                }
            });
        }
    }


    public static class testCla {
        //        public  synchronized void testSync() {  //.修饰在方法上,多个线程调用同一个对象的同步方法会阻塞,调用不同对象的同步方法不会阻塞。
        public void testSync() {
            String obj = new String("zsw");
            synchronized (obj) {  // 锁的是String对象。
//            synchronized (this) { //这个this就是指当前对象(类的实例),多个线程调用同一个对象的同步方法会阻塞,调用不同对象的同步方法不会阻塞。(java对象的内存地址是否相同)
//            synchronized (testCla.class) {  //锁的对象是testCla.class 类,即testCla类的锁。
                log.info("锁的是SynCla对象");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                int i = 0;
                i++;
                log.info("结束:{}", i);
            }

        }
    }


}

ReentrantLock

package com.thread.sync;

import com.sun.org.apache.xpath.internal.operations.String;

import java.util.concurrent.locks.ReentrantLock;

/**
 * @author zsw
 * @date 2021/1/21 10:46
 * @description :
 * java5之后,并发包中新增了Lock接口(以及相关实现类)用来实现锁的功能,它提供了与synchronized关键字类似的同步功能。
 * 既然有了synchronized这种内置的锁功能,为何要新增Lock接口?先来想象一个场景:手把手的进行锁获取和释放,先获得锁A,然后再获取锁B,当获取锁B后释放锁A同时获取锁C,当锁C获取后,再释放锁B同时获取锁D,
 * 以此类推,这种场景下,synchronized关键字就不那么容易实现了,而使用Lock却显得容易许多。
 * 使用方式:
 * Lock lock = new ReentrantLock();
 * Condition condition = lock.newCondition();
 * lock.lock();
 * try {
 *   while(条件判断表达式) {
 *       condition.wait();
 *   }
 *  // 处理逻辑
 * } finally {
 *     lock.unlock();
 * }
 *需要显示的获取锁,并在finally块中显示的释放锁,目的是保证在获取到锁之后,最终能够被释放。
 * -----------------------------------------------------------------
 * java中已经有了内置锁:synchronized,synchronized的特点是使用简单,一切交给JVM去处理,不需要显示释放
 * 从用法上可以看出,与synchronized相比, ReentrantLock就稍微复杂一点。因为必须在finally中进行解锁操作,如果不在 finally解锁,有可能代码出现异常锁没被释放,
 *ReentrantLock的性能是明显优于synchronized的,ReentrantLock在功能上更加丰富,它具有可重入、可中断、可限时、公平锁等特点。
 */
public class ReentrantLockTest extends Thread {
    public static ReentrantLock lock = new ReentrantLock();
    public static int i=0;

    public ReentrantLockTest(java.lang.String thread1) {
        super.setName(thread1);
    }

    @Override
    public void run() {
        for (int j = 0; j < 1000; j++) {
            lock.lock();
            try {
                System.out.println(this.getName() + " " + i);
                i++;
            } finally {
                lock.unlock();
            }
        }

    }

    public static void main(String[] args) {
        ReentrantLockTest thread1 = new ReentrantLockTest("thread1");
        ReentrantLockTest thread2 = new ReentrantLockTest("thread2");
        thread1.start();
        thread2.start();
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(i);
    }



}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值