1.5分飞艇邀请码_Java多线程,对锁机制的进一步分析

  • 时间:
  • 浏览:2
  • 来源:轻旭博客 - 专注共享诗梦博客分享

1 可重入锁

    可重入锁,也叫递归锁。它有两层含义,第一,当这么 系统多多线程 在外层函数得到可重入锁后,能直接递归地调用该函数,第二,同一系统多多线程 在外层函数获得可重入锁后,内层函数还可不还可以 直接获取该锁对应其它代码的控制权。已经 亲戚亲戚什儿 人提到的synchronized和ReentrantLock总要可重入锁。

    通过ReEnterSyncDemo.java,亲戚亲戚什儿 人来演示下synchronized关键字的可重入性。    

1	class SyncReEnter implements Runnable{
2	   public synchronized void get(){
3	     System.out.print(Thread.currentThread().getId() + "\t");
4	      //在get土法律依据里调用set
5	      set();
6	    }
7	    public synchronized void set()
8	    {System.out.print(Thread.currentThread().getId()+"\t"); }
9	    public void run() //run土法律依据里调用了get土法律依据
10	    { get();}
11	}
12	public class ReEnterSyncDemo {
13	    public static void main(String[] args) {
14	       	SyncReEnter demo=new SyncReEnter();
15	        new Thread(demo).start();
16	        new Thread(demo).start();
17	    }
18	}

    在第1行里,亲戚亲戚什儿 人是让syncReEnter类通过实现Runnable的土法律依据来实现多系统多多线程 ,在其中第2和第7行所定义的get和set土法律依据均富含synchronized关键字。在第9行定义的run土法律依据里,亲戚亲戚什儿 人调用了get土法律依据。在main函数的第15和16行里,亲戚亲戚什儿 人启动了2次系统多多线程 ,这段代码的输出如下。

    8   8   9   9  

    在第15行第一次启动系统多多线程 时,在run土法律依据里,会调用富含synchronized关键字的get土法律依据,这时什儿 系统多多线程 会得到get土法律依据的锁,当执行到get里的set土法律依据时,是因为 set土法律依据也富含synchronized关键字,已经 set是富含在get里的,太满太满这里不会再次申请set的锁,能继续执行,太满太满通过输出,亲戚亲戚什儿 人能想看 get和set的打印语句是连续输出的。同理亲戚亲戚什儿 人能理解第16行第二次启动系统多多线程 的输出。

    通过ReEnterLock.java,亲戚亲戚什儿 人来演示下ReentrantLock的可重入性。      

1	import java.util.concurrent.locks.ReentrantLock;
2	class LockReEnter implements Runnable {
3		ReentrantLock lock = new ReentrantLock();
4		public void get() {
5		  lock.lock();
6	  	  System.out.print(Thread.currentThread().getId()+"\t");
7		  // 在get土法律依据里调用set
8		  set();
9		  lock.unlock();
10	   }
11	   public void set() {
12		lock.lock();
13		System.out.print(Thread.currentThread().getId() + "\t");
14		lock.unlock();
15	   }
16	   public void run() 
17	   { get(); }
18	}
19	public class ReEnterLock {
20		public static void main(String[] args) {
21			LockReEnter demo = new LockReEnter();
22			new Thread(demo).start();
23			new Thread(demo).start();
24		}
25	}

    在第2行创建的LockReEnter类里,亲戚亲戚什儿 人同样富含了get和set土法律依据,并在get土法律依据里调用了set土法律依据,只不过在get和set土法律依据里,亲戚亲戚什儿 人总要用synchronized,太满太满我用第3行定义的ReentrantLock类型的lock对象来管理多系统多多线程 的并发,在第16行的run土法律依据里,亲戚亲戚什儿 人同样地调用了get土法律依据。

    在main函数里,亲戚亲戚什儿 人同样地在第22和23行里启动了两次系统多多线程 ,这段代码的运行结果如下。

    8   8   9   9

    当在第22行里第一次启动LockReEnter类型的系统多多线程 后,在调用get土法律依据时,能得到第5行的锁对象,get土法律依据会调用set土法律依据,什儿 set土法律依据里的第12行会再次申请锁,但是因为 LockReEnter系统多多线程 在get土法律依据里是因为 得到了锁,太满太满在set土法律依据还可不还可以 够得到锁,太满太满第一次运行时,get和set土法律依据会同時 执行,同样地,在第23行第二次其中系统多多线程 时,也会同時 打印get和set土法律依据里的输出。

    在项目的什儿 场景里,这么 系统多多线程 有是因为 时需多次进入被锁关联的土法律依据,比如某数据库的操作的系统多多线程 时需多次调用被锁管理的“获取数据库连接”的土法律依据,这时,是因为 使用可重入锁就能处置死锁的什么的问题,相反,是因为 亲戚亲戚什儿 人总要用可重入锁,这么在第二次调用“获取数据库连接”土法律依据时,总要是因为 被锁住,从而是因为 死锁什么的问题。

2 公平锁和非公平锁

    在创建Semaphore对象时,亲戚亲戚什儿 人还可不还可以 通过第这么 参数,来指定该Semaphore对象否是以公平锁的土法律依据来调度资源。

    公平锁会维护这么 等待队列,多个在阻塞情况汇报等待的系统多多线程 会被插入到什儿 等待队列,在调度时是按它们所发请求的时间顺序获取锁,而对于非公平锁,当这么 系统多多线程 请求非公平锁时,是因为 此时该锁变成可用情况汇报,这么什儿 系统多多线程 会跳过等待队列中所有的等待系统多多线程 而获得锁。

    亲戚亲戚什儿 人在创建可重入锁时,也还可不还可以 通过调用带布尔类型参数的构造函数来指定该锁否是公平锁。ReentrantLock(boolean fair)。

    在项目里,是因为 请求锁的平均时间间隔较长,建议使用公平锁,反之建议使用非公平锁。

    比如有个服务窗口,是因为 采用非公平锁的土法律依据,当窗口空闲时,总要让下一号来,太满太满我倘若来人就服务,另这么 能缩短窗口的空闲等待,从而提升单位时间内的服务数量(也太满太满我吞吐量)。相反,是因为 这是个比较冷门的服务窗口,在太满太满时间里来请求服务的频次何必 高,比如一小时才来这么 人,这么就还可不还可以 选着公平锁了。是因为 ,是因为 要缩短用户的平均等待,这么还可不还可以 选着公平锁,另这么 就能处置“早到的请求晚处置“的情况汇报。

3 读写锁

    已经 亲戚亲戚什儿 人通过synchronized和ReentrantLock来管理临界资源时,只太满太满我这么 系统多多线程 得到锁,其它系统多多线程 只能操作什儿 临界资源,什儿 锁还可不还可以 叫做“互斥锁”。

    和什儿 管理土法律依据相比,ReentrantReadWriteLock对象会使用两把锁来管理临界资源,这么 是“读锁“,另这么 是“写锁“。

    是因为 这么 系统多多线程 获得了某资源上的“读锁“,这么其它对该资源执行“读操作“的系统多多线程 还是还可不还可以 继续获得该锁,也太满太满我说,“读操作“还可不还可以 并发执行,但执行“写操作“的系统多多线程 会被阻塞。是因为 这么 系统多多线程 获得了某资源的“写锁“,这么其它任何企图获得该资源“读锁“和“写锁“的系统多多线程 都将被阻塞。

    和互斥锁相比,读写锁在保证并发时数据准确性的同時 ,允什儿 个系统多多线程 同時 “读“某资源,从而能提升效率。通过下面的ReadWriteLockDemo.java,亲戚亲戚什儿 人来观察下通过读写锁管理读写并发系统多多线程 的土法律依据。    

1	import java.util.concurrent.locks.Lock;
2	import java.util.concurrent.locks.ReentrantReadWriteLock;
3	class ReadWriteTool {
4		private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
5		private Lock readLock = lock.readLock();
6		private Lock writeLock = lock.writeLock();
7		private int num = 0;
8	  	public void read() {//读的土法律依据 
9			int cnt = 0;
10			while (cnt++ < 3) {
11				try {
12					readLock.lock();				System.out.println(Thread.currentThread().getId()
13							+ " start to read");
14					Thread.sleep(50);		
15		System.out.println(Thread.currentThread().getId() + " reading,"	+ num);
16				} catch (Exception e) 
17	            { e.printStackTrace();}
18	            finally { readLock.unlock(); 	}
19			}
20		}
21		public void write() {//写的土法律依据
22			int cnt = 0;
23			while (cnt++ < 3) {
24				try {
25					writeLock.lock();		
26			System.out.println(Thread.currentThread().getId()
27							+ " start to write");
28					Thread.sleep(50);
29					num = (int) (Math.random() * 10);
50				System.out.println(Thread.currentThread().getId() + " write," + num);
31				} catch (Exception e) 
32	            { e.printStackTrace();} 
33	            finally { writeLock.unlock();}
34			}
35		}
36	}

    在第3行定义的ReadWriteTool 类里,亲戚亲戚什儿 人在第4行创建了这么 读写锁,并在第5和第6行,分别通过什儿 读写锁的readLock和writeLock土法律依据,分别创建了读锁和写锁。

    在第8行的read土法律依据里,亲戚亲戚什儿 人是先通过第12行的代码加“读锁“,已经 在第15行进行读操作。在第21行的write土法律依据里,亲戚亲戚什儿 人是先通过第25行的代码加“写锁”,已经 在第50行进行写操作。    

37	class ReadThread extends Thread {
38		private ReadWriteTool readTool;
39		public ReadThread(ReadWriteTool readTool) 
40	    { this.readTool = readTool;	}
41		public void run() 
42	    { readTool.read();}
43	}
44	class WriteThread extends Thread {
45		private ReadWriteTool writeTool;
46		public WriteThread(ReadWriteTool writeTool) 
47	    { this.writeTool = writeTool; }
48		public void run() 
49	    { writeTool.write();	}
50	}

    在第37行和第44行里,亲戚亲戚什儿 人分别定义了读和写这这么 系统多多线程 ,在ReadThread系统多多线程 的run土法律依据里,亲戚亲戚什儿 人调用了ReadWriteTool类的read土法律依据,而在WriteThread系统多多线程 的run土法律依据里,则调用了write土法律依据。    

51	public class ReadWriteLockDemo {
52		public static void main(String[] args) {
53			ReadWriteTool tool = new ReadWriteTool();
54			for (int i = 0; i < 3; i++) {
55				new ReadThread(tool).start();
56				new WriteThread(tool).start();
57			}
58		}
59	}

    在main函数的第53行,亲戚亲戚什儿 人创建了这么 ReadWriteTool类型的tool对象,在第55和56行初始化读写系统多多线程 时,亲戚亲戚什儿 人传入了该tool对象,也太满太满我说,通过54行for循环创建并启动的多个读写系统多多线程 是通过同这么 读写锁来控制读写并发操作的。

    出于多系统多多线程 并发调度的是因为 ,亲戚亲戚什儿 人每次运行都是因为 得到不同的结果,但从那些不同的结果里,亲戚亲戚什儿 人都態明显地看出读写锁协调管理读写系统多多线程 的土法律依据,比如来看下如下的每项输出结果。    

1	8 start to read
2	10 start to read
3	12 start to read
4	8 reading,0
5	10 reading,0
6	12 reading,0
7	9 start to write
8	9 write,2
9	11 start to write
10	11 write,6

    这里亲戚亲戚什儿 人是通过ReadWriteTool类里的读写锁管理其中的num值,从第1到第6行的输出中亲戚亲戚什儿 人能想看 ,什儿 8号系统多多线程 是因为 得到读锁现在已经 刚现在开始读num资源时,10号和12号读系统多多线程 依随还可不还可以 得到读锁,从而能并发地读取num资源。但在读操作期间,是不允许有写操作的系统多多线程 进入,也太满太满我说,当num资源上有读锁期间,其它系统多多线程 是无法得到该资源上的“写锁”的。

    从第7到第10行的输出中亲戚亲戚什儿 人能想看 ,当9号系统多多线程 得到num资源上的“写锁”时,其它系统多多线程 是无法得到该资源上的“读锁“和“写锁“的,而11号系统多多线程 一定得当9号系统多多线程 释放了“写锁”后,能够得到num资源的“写锁”。

    是因为 在项目里对什儿 资源(比如文件)有读写操作,这时亲戚亲戚什儿 人不妨还可不还可以 使用读写锁,是因为 读操作的数量要远超过写操作时,这么更还可不还可以 用读写锁来让读操作还可不还可以 并发执行,从而提升性能。