Java多线程synchronized与ReentrantLock的区别

synchronized 与 ReentrantLock

前言

1)synchronized函数锁的是this,ReentrantLock锁的是也是this,synchronized块自定义锁对象。
2)并发的控制在源头,将并发操作的核心即操作独占资源放在资源对象里,并加锁,把源头控制住,再多线程都不怕。

一、ArrayList为例

package com.xhu.java.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

//测试lock锁到底在锁什么?
public class TestReentrantLock {
    public static void main(String[] args) throws InterruptedException {
        //一份核心资源
        CoreResource cr = new CoreResource();
        //两个线程用
        Thread1 t1 = new Thread1(cr);
        Thread2 t2 = new Thread2(cr);
        // 启动两个线程同时操作资源
        new Thread(t1).start();
        new Thread(t2).start();
        //等两个线程跑完
        Thread.sleep(5000);
        //查看核心资源的大小
        System.out.println(cr.getResource().size());
        //主线程再等待5秒
        Thread.sleep(5000);
        //如果两者的结果一致,说明其它线程已经跑完。该结果才可作为最后的结果
        System.out.println(cr.getResource().size());
        //test1:无锁情况操作同一资源,size本应该是200w,测试结果=1749696
        //test2:加ReentrantLock在两个线程体,size本应该是200w,测试结果=15983189,初步猜测ReentrantLock锁的是this
        //test3:加ReentrantLock在并发的源头,也就是独占资源处,本应该的size = 测试结果
        //test4:synchronized 控制源头,也就是独占资源处,本应该的size = 测试结果
        //test5:在两个线程体里用synchronized去锁独占资源,本应该的size = 测试结果
        //总结:1.synchronized函数与ReentrantLock锁的都是this。2.并发源于独占资源处,所以并发操作应该写在源头处,管理好源头,其它线程就不会乱。
    }
}

//争夺资源的线程1
class Thread1 implements Runnable {
    //争夺的核心资源
    private CoreResource cr;
    private ReentrantLock rl = new ReentrantLock();

    public Thread1(CoreResource cr) {
        this.cr = cr;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000000; i++) {
            synchronized (cr) {
                cr.add(i);
            }
        }
    }
}

//争夺资源的线程2
class Thread2 implements Runnable {
    //核心资源只有一份
    private CoreResource cr;
    //private ReentrantLock rl = new ReentrantLock();

    public Thread2(CoreResource cr) {
        this.cr = cr;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000000; i++) {
            synchronized (cr) {
                cr.add(i);
            }
        }
    }
}

//独占资源类ArrayList
class CoreResource {
    private List<Integer> resource = new ArrayList<>();
    private ReentrantLock rl = new ReentrantLock();

    //独占资源应该在独占资源处操作,便于管理,管理并发的源头。
    public void add(int i) {
        //rl.lock();
        resource.add(i);
        //rl.unlock();
    }

    public List<Integer> getResource() {
        return resource;
    }

    public void setResource(List<Integer> resource) {
        this.resource = resource;
    }
}

总结

1)分清楚一个线程体多个线程执行、多个线程体多个线程执行,但是它们都操作同一资源的区别。
2)独占资源才是并发的核心,设计并管理好独占资源类。

附录

[1] Java 多线程入门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值