Java并发编程中的锁
2024-10-21 02:47:22
synchronized
使用synchronized实现同步有2种方式:
- 同步方法(静态与非静态)
- 同步代码块
任何Java对象均可作为锁使用,其中,使用的锁对象有以下3种:
- 静态同步方法中,锁是当前类的Class对象
- 非静态同步方法中,锁是当前对象this(调用该方法的对象)
- 同步代码块中,琐是手动配置的对象
同步方法
private synchronized void f()
{
//...
}
同步代码块
private void f()
{
synchronized(this)
{
//...
}
}
Lock
Lock接口
中规定了锁必须实现的一些方法
void lock()
void unlock()
boolean tryLock()
boolean tryLock(long time, TimeUnit unit)
Condition newCondition()
Lock接口的实现类有ReentarntLock
和ReentrantReadWriteLock
2种,它们都提供了非公平锁和公平锁2种形式。
ReentrantLock
可重入锁,线程可以重复的获取已经持有的锁。
锁中维护着一个持有计数,来追踪对lock方法的嵌套调用,每次lock计数加1,每次unlock计数减1。
只有持有计数为0时,才释放锁。
使用示例
private Lock lock=new ReentrantLock();
private void f()
{
lock.lock();
try
{
// ...
}
finally
{
lock.unlock();
}
}
公平锁,线程调度器将优先(并不保证一定)执行等待时间最长的线程。
在创建ReentrantLock时,可以传入Boolean参数true,创建一个公平锁。
Lock fairLock=new ReentrantLock(true);
除了使用lock()
获取锁外,还可以使用tryLock()
尝试获取锁,如果成功,返回true,否则,返回false,并且线程可以立即离开去做其它事情。
还可以调用传入超时参数。
ReentrantReadWriteLock
可重入读写锁。如果对一个数据结构进行读操作的次数远远大于写操作的次数,就可以使用读写锁提高性能。
使用示例
private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();// 创建读写锁
private Lock readLock=lock.readLock();// 读锁
private Lock writeLock=lock.writeLock();// 写锁
// 读操作加读锁
public void read()
{
readLock.lock();
try
{
// ...
}
finally
{
readLock.unlock();
}
}
// 写操作加写锁
public void write()
{
writeLock.lock();
try
{
// ...
}
finally
{
writeLock.unlock();
}
}
死锁
死锁问题的产生,是由于线程A和线程B互相持有对方需要获取的锁对象导致的
private static final Object lockA=new Object();
private static final Object lockB=new Object();
private void deadLock()
{
Thread t1=new Thread(()->{
synchronized(lockA)
{
sleep(1L);
synchronized(lockB)
{
System.out.println("thread 1");
}
}
});
Thread t2=new Thread(()->{
synchronized(lockB)
{
sleep(1L);
synchronized(lockA)
{
System.out.println("thread 2");
}
}
});
t1.start();
t2.start();
}
private void sleep(long timeout)
{
try
{
TimeUnit.SECONDS.sleep(timeout);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
死锁问题一旦发生,程序就会挂起。所以,必须避免死锁的发生,有以下几个方式
- 避免在一个线程中同时获取多个锁
- 尝试使用定时锁(
lock.tryLock(timeout)
),替代普通锁机制
最新文章
- mysql 基础 增删改查语句
- VB编程的键盘控制
- HTML5中使用图片传递密文
- 优化 bulk insert
- getview不执行
- Android Studio-设置快速修复错误提示代码
- Hql查询结果动态组装 List(map),List(bean),List(list),List(set)等格式(转)
- move语义和右值引用
- Android微信SDK API 调用教程1
- Membership角色与权限管理
- Java字符串的10大热点问题,你都懂吗?
- ADO.NET之使用DataGridView控件显示从服务器上获取的数据
- SQL语句函数详解__sql聚合函数
- Swing 显示良好JPanel保存为图片
- Android开发学习-view
- HttpClient4.5 post请求xml到服务器
- 简单实用的jQuery分页插件
- Nginx禁止目录执行php文件权限
- luogu P4178 Tree
- C# ThreadStart和ParameterizedThreadStart区别