目录
ReentrantReadWriteLock和ReentrantLock区别
Runnable 和Thread区别
- Runnable 是接口,Thread 是类,且实现了Runnable接口。
- Runnable定义的子类中没有start方法,只有在Thread类类中有。
- Thread类中只有一个构造方法,public Thread(Runnable targer),该构造方法接受Runnable的所有子类的实例,可以通过Thread类来启动runnable来实现多线程。
在实际开发中多使用实现Runnable接口原因
- 因为与继承Thread类相比,很好的解决了java中只能单继承的限制,通过接口来实现继承。
- runnbal实现资源共享,而Thraed类中每个线程独立不共享。
- 实现Runnable接口实现了资源共享,出现乱序使用同步关键词(synchronized)
- 但是如果使用synchronized时,一个线程出现了阻塞,但是又没有释放锁,线程只能等待,影响效率。
- 通过Lock锁机制来使多个线程实现读写操作,解决线程之间发生冲突。ReadWriteLock是一个接口,在它里面只定义了两个方法:一个读的锁和一个写的锁。读的锁:A线程获取了读的锁,那么B线程也可以获取读的锁。写的锁:A线程获取了写的锁,那么B线程不能获取读也不能获取写的锁。(具体内容见下文介绍)
public class MyThreadWithImplements implements Runnable {
private int tickets = 10;
@Override
public synchronized void run() {
for (int i = 0; i <= 100; i++) {
if(tickets>0){
System.out.println(Thread.currentThread().getName()+"--卖出票:" + tickets--);
}
}
}
public static void main(String[] args) {
MyThreadWithImplements myRunnable = new MyThreadWithImplements();
Thread thread1 = new Thread(myRunnable, "窗口一");
Thread thread2 = new Thread(myRunnable, "窗口二");
Thread thread3 = new Thread(myRunnable, "窗口三");
thread1.start();
thread2.start();
thread3.start();
}
锁介绍
1、可重入锁(ReenTrant)
像synchronized和 ReentrantLock都是可重入锁,可重入性在我看来实际上表明了锁的分配机制:基于线程的分配,而不是基于方法调用的分配。
2、可中断锁
synchronized不是可中断锁,Lock是可中断锁。
3、公平锁
①公平锁即尽量以请求锁的顺序来获取锁。比如同是有多个线程在等待一个锁,当这个锁被释放时,等待时间最久的线程(最先请求的线程)会获得该所,这种就是公平锁。非公平锁即无法保证锁的获取是按照请求锁的顺序进行的。这样就可能导致某个或者一些线程永远获取不到锁。
②synchronized就是非公平锁,它无法保证等待的线程获取锁的顺序。
③ReentrantLock和ReentrantReadWriteLock,它默认情况下是非公平锁,但是可以设置为公平锁。
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
4、读写锁
synchronized读锁和读锁互斥, ReentrantReadWriteLock为读和读为共享锁
Synchronized同步关键词
一个代码块被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁。这种特性又被称为互斥锁
而这里获取锁的线程释放锁只会有两种情况:
- 获取锁的线程执行完了该代码块,然后线程释放对锁的占有。
- 线程执行发生异常,此时JVM会让线程自动释放锁。
lock和synchronized区别
- Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这个类可以实现同步访问;
- Lock和synchronized有一点非常大的不同,采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。
- Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
- 通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
- Lock可以提高多个线程进行读操作的效率。
ReentrantReadWriteLock和ReentrantLock区别
ReentrantReadWriteLock是Lock的另一种实现方式,我们已经知道了ReentrantLock是一个排他锁,同一时间只允许一个线程访问,而ReentrantReadWriteLock允许多个读线程同时访问,但不允许写线程和读线程、写线程和写线程同时访问。相对于排他锁,提高了并发性。在实际应用中,大部分情况下对共享数据(如缓存)的访问都是读操作远多于写操作,这时ReentrantReadWriteLock能够提供比排他锁更好的并发性和吞吐量。
读写锁内部维护了两个锁,一个用于读操作,一个用于写操作。所有 ReadWriteLock实现都必须保证 writeLock操作的内存同步效果也要保持与相关 readLock的联系。也就是说,成功获取读锁的线程会看到写入锁之前版本所做的所有更新。
ReentrantReadWriteLock支持以下功能:
- 支持公平和非公平的获取锁的方式;
- 支持可重入。读线程在获取了读锁后还可以获取读锁;写线程在获取了写锁之后既可以再次获取写锁又可以获取读锁;
- 还允许从写入锁降级为读取锁,其实现方式是:先获取写入锁,然后获取读取锁,最后释放写入锁。但是,从读取锁升级到写入锁是不允许的;
- 读取锁和写入锁都支持锁获取期间的中断;
- Condition支持。仅写入锁提供了一个 Conditon 实现;读取锁不支持 Conditon ,readLock().newCondition() 会抛出 UnsupportedOperationException。
public class LearnDemo
{
private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
public static void main (String[] args){
final LearnDemo userRrw = new LearnDemo();
new Thread(new Runnable(){
@Override
public void run() {
userRrw.get(Thread.currentThread());
userRrw.write(Thread.currentThread());
}
}).start();
}
public void get(Thread thread){
reentrantReadWriteLock.readLock().lock();
try{
long start = System.currentTimeMillis();
System.out.println("start = "+start);
while(System.currentTimeMillis()-start<=1){
System.out.println("System.currentTimeMillis() = "+start);
System.out.println(thread.getName()+"执行读操作");
}
System.out.println(thread.getName()+"读操作执行完毕");
}catch(Exception e){
e.printStackTrace();
}finally {
reentrantReadWriteLock.readLock().unlock();
}
}
public void write(Thread thread){
reentrantReadWriteLock.writeLock().lock();
try{
Long start = System.currentTimeMillis();
while(System.currentTimeMillis()-start<=1){
System.out.println(thread.getName()+"执行写操作");
}
System.out.println(thread.getName()+"写操作执行完毕");
}catch (Exception e){
e.printStackTrace();
}finally {
reentrantReadWriteLock.writeLock().unlock();
}
}
}
参考文章:https://blog.csdn.net/zengmingen/article/details/53217229
本文深入探讨Java多线程的实现方式,对比Runnable接口与Thread类的区别,讲解锁机制,包括synchronized关键字、Lock接口及其子类ReentrantLock与ReentrantReadWriteLock的特性和应用场景。
&spm=1001.2101.3001.5002&articleId=87279722&d=1&t=3&u=2d20830e39a34c25864d5c33f567b5fd)
451

被折叠的 条评论
为什么被折叠?



