Java并发编程中的锁
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和ReentrantReadWriteLock2种,它们都提供了非公平锁和公平锁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)),替代普通锁机制
Java并发编程中的锁的更多相关文章
- Java并发编程中的相关注解
		引自:http://www.cnblogs.com/phoebus0501/archive/2011/02/21/1960077.html Java并发编程中,用到了一些专门为并发编程准备的 Anno ... 
- Java并发编程中的设计模式解析(二)一个单例的七种写法
		Java单例模式是最常见的设计模式之一,广泛应用于各种框架.中间件和应用开发中.单例模式实现起来比较简单,基本是每个Java工程师都能信手拈来的,本文将结合多线程.类的加载等知识,系统地介绍一下单例模 ... 
- Java并发编程:Concurrent锁机制解析
		Java并发编程:Concurrent锁机制解析 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: # ... 
- Java并发编程中的若干核心技术,向高手进阶!
		来源:http://www.jianshu.com/p/5f499f8212e7 引言 本文试图从一个更高的视角来总结Java语言中的并发编程内容,希望阅读完本文之后,可以收获一些内容,至少应该知道在 ... 
- Java并发编程中的设计模式解析(一)
		Java并发编程,除了被用于各种Web应用.分布式系统和大数据系统,构成高并发系统的核心基础外,其本身也蕴含着大量的设计模式思想在里面.这一系列文章主要是结合Java源码,对并发编程中使用到的.实现的 ... 
- Java并发编程:同步锁、读写锁
		之前我们说过线程安全问题可以用锁机制来解决,即线程必要要先获得锁,之后才能进行其他操作.其实在 Java 的 API 中有这样一些锁类可以提供给我们使用,与其他对象作为锁相比,它们具有更强大的功能. ... 
- Java并发编程中线程池源码分析及使用
		当Java处理高并发的时候,线程数量特别的多的时候,而且每个线程都是执行很短的时间就结束了,频繁创建线程和销毁线程需要占用很多系统的资源和时间,会降低系统的工作效率. 参考http://www.cnb ... 
- Java 并发编程中的 Executor 框架与线程池
		Java 5 开始引入 Conccurent 软件包,提供完备的并发能力,对线程池有了更好的支持.其中,Executor 框架是最值得称道的. Executor框架是指java 5中引入的一系列并发库 ... 
- Java 并发编程中的 CountDownLatch 锁用于多个线程同时开始运行或主线程等待子线程结束
		Java 5 开始引入的 Concurrent 并发软件包里面的 CountDownLatch 其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,同时只能有一个线程去操作这个计数器,也就是 ... 
随机推荐
- multiset容器erase函数的误用
			<从缺陷中学习C/C++>第3章库函数问题,本章主要介绍库函数的使用中会遇到的问题.使用库函数可以降低软件开发的难度,提高代码编写的效率.本节为大家介绍multiset容器erase函数的 ... 
- php中输出函数的区别
			isset() .empty()与is_null的区别 1.当变量未定义时,is_null() 和"参数本身"是不允许作为参数判断的,会报Notice警告错误: 2.empty , ... 
- linux如何patch打补丁
			1. 创建2个文件 1.txt 和 2.txt 并在1.txt基础上修改成为2.txt book@100ask:~/patch$ ls 1.txt 2.txt book@100ask:~/patch$ ... 
- linux-TCP多线程的并发服务器- 以言责人甚易,以义持己实难!!!
			1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <ti ... 
- ]# dmesg | grep ATAcentos下查看网卡,主板,CPU,显卡,硬盘型号等硬件信息
			centos下查看网卡,主板,CPU,显卡,硬盘型号等硬件信息 osc_4o5tc4xq 2019/10/11 15:03 阅读数 253 centos下查看网卡,主板,CPU,显卡,硬盘型号等硬件信 ... 
- jmeter完成一个简单的性能测试(jp@gc - PerfMon Metrics Collector的运用)
			场景:公司项目解耦,在项目前期对新的架构进行简单的性能测试 工具:jmeter 1.大致结构如下: 1800秒(半个小时)内持续产生20000的线程 创建了聚合报告,主要是查看服务器响应结果以及相应时 ... 
- linux进阶之子网划分
			一.定义 当我们对一个网络进行子网划分时,基本上就是将它分成小的网络.比如,当一组IP地址指定给一个公司时,公司可能将该网络"分割成"小的网络,每个部门一个.这样,技术部门和管理部 ... 
- 华为4D成像雷达、智能驾驶平台MDC 810
			华为4D成像雷达.智能驾驶平台MDC 810 2020年10月底,华为发布了HI品牌,在今年2021年上海国际车展前夕,华为以 "专新致智" 为主题,举办HI新品发布会,发布了包括 ... 
- TVM交叉编译和远程RPC
			TVM交叉编译和远程RPC 本文介绍了TVM中使用RPC的交叉编译和远程设备执行. 使用交叉编译和RPC,可以在本地计算机上编译程序,然后在远程设备上运行它.当远程设备资源受到限制时(如Raspber ... 
- 将Tensor核心引入标准Fortran
			将Tensor核心引入标准Fortran 调优的数学库是从HPC系统提取最终性能的一种简单而可靠的方法.但是,对于寿命长的应用程序或需要在各种平台上运行的应用程序,为每个供应商或库版本调整库调用可能是 ... 
