java holdslock_Java并发编程-锁

锁的主要知识点有:

悲观锁/乐观锁

独享锁/共享锁

公平锁/非公平锁

可重入锁

分段锁

自旋锁

分布式锁

1、乐观锁/悲观锁

悲观锁/乐观锁体现的是一种思想,不是指具体什么类型的锁。

悲观锁总是假设最坏的情况,每次拿数据都会上锁,这样共享资源只能被一个线程使用阻塞其他线程,当用完后才释放锁让其他线程可以使用锁。Java中的synchronized和ReentrantLock就是悲观锁。数据库中的表锁和行锁也是悲观锁。

乐观锁总是假设最好的情况,每次拿数据的时候总是认为别人不会修改。其实乐观锁就是不加锁,一般通过CAS算法(Compare and Swap)来保证操作正确。Java包java.util.concurrent.atomic下所有原子类都体现这种思想,如AtomicInteger.compareAndSet(int expect, int update),还有数据库操作update xxx set data=xxx, version=version+1 where id=xxx and version=xxx,在更新失败后可以重试。

3、独享锁/共享锁

独享锁同时只能被一个线程获得,synchronized、ReentrantLock和ReentrantReadWriteLock.WriteLock就是独享锁。

共享锁同时可以被多个线程获得。ReentrantReadWriteLock.ReadLock就是典型的共享锁。

4、公平锁/非公平锁

公平锁就是所有线程按照先到先得的原则申请锁。

非公平锁就是线程同时抢占锁,这样的坏处是可能导致某些线程始终无法申请到锁。

ReentrantLock可以通过构造函数参数fair设定是否为公平锁,默认为非公平锁。ReentrantLock内部维护了一个队列,记录了每个线程申请锁的顺序,lock操作采用for循环的方式申请锁(compareAndSetState),对于非公平锁,所有线程同时尝试申请锁,公平锁则还要判断当前线程处于队列中的位置,当在它之前没有线程时才申请锁。ReentrantLock和synchronized都可以实现非公平锁,他们的不同在于ReentrantLock可以中断,可以设置超期时间,使用上更加灵活。

5、分段锁

分段锁是一种设计,它不需要对操作对象整个加锁,分段锁将操作对象分成若干个区域,操作数据时我们先判断数据所在的区域,然后对这个区域加锁,防止其他线程操作这个区域的数据,通过又不影响其他区域数据的操作。Java中ConcurrentHashMap就实现了分段锁,每一个插槽都可以加锁。

6、分布式锁

在单一系统中访问共享变量我们通过各种锁达到线程安全,但分布式系统中,系统间是独立,一个系统无法感知另外一个系统对共享数据的修改

7、如何检测一个线程是否拥有锁,使用Thread.holdsLock(),只能检测当前线程是否有锁

public classHoldsLockTest {

Object o= newObject();

@Testpublic void test() throwsException {new Thread(newRunnable() {

@Overridepublic voidrun() {synchronized(o) {

System.out.println("子线程是否有锁:" +Thread.holdsLock(o));

}

}

}).start();

System.out.println("主线程是否有锁:" +Thread.holdsLock(o));

Thread.sleep(2000);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值