在Java多线程中,可以使用关键字Synchronized实现线程之间互斥。在JDK1.5之后,提供了线程并发库java.util.concurrent用于操作多线程,其中包含了java.util.concurrent.atomic和java.util.concurrent.lock。atomic可以实现数据或变量的原子性操作,而lock可以实现线程互斥,可以实现读写锁,跟Synchronized一样同属于可重入锁,但在使用上比Synchronized更加灵活。
在代码中,可以通过new ReentrantLock()创建一个lock锁,调用lock()实现对代码上锁,调用unlock()可以解锁。当然,为了保证代码运行出现异常时也能解锁,应该把上锁的代码用try包裹起来,并在finally里解锁,具体代码实现如下:
[java]
1. public class Main {
2. //静态内部类实现线程共享
3. static class Example{
4. //创建lock
5. new ReentrantLock();
6. public void outPut(String str){
7. //上锁
8. lock.lock();
9. try{
10. for(int i=0;i<str.length();i++){
11. System.out.print(str.charAt(i));
12. }
13. "\n");
14. finally {
15. //解锁
16. lock.unlock();
17. }
18. }
19. }
20.
21. public static void main(String[] args) {
22. final Example example = new Example();
23. new Thread(new Runnable() {
24. @Override
25. public void run() {
26. while (true){
27. "str1");
28. }
29. }
30. }).start();
31. new Thread(new Runnable() {
32. @Override
33. public void run() {
34. while (true){
35. "str2");
36. }
37. }
38. }).start();
39. }
40. }
对于lock的读写锁,可以通过new ReentrantReadWriteLock()获取到一个读写锁。所谓读写锁,便是多线程之间读不互斥,读写互斥。读写锁是一种自旋锁,如果当前没有读者,也没有写者,那么写者可以立刻获得锁,否则它必须自旋在那里,直到没有任何写者或读者。如果当前没有写者,那么读者可以立即获得该读写锁,否则读者必须自旋在那里,直到写者释放该锁。具体代码实现如下:
[java]
1. public class Main {
2. //静态内部类实现线程共享
3. static class Example{
4. //创建lock
5. new ReentrantReadWriteLock();
6. //读操作
7. public void read(){
8. //获取读锁并上锁
9. lock.readLock().lock();
10. try{
11. "读线程开始");
12. 1000);
13. "读线程结束");
14. catch (Exception e){
15. e.printStackTrace();
16. finally{
17. //解锁
18. lock.readLock().unlock();
19. }
20. }
21. //写操作
22. public void write(){
23. //获取写锁并上锁
24. lock.writeLock().lock();
25. try{
26. "写线程开始");
27. 1000);
28. "写线程结束");
29. catch (Exception e){
30. e.printStackTrace();
31. finally {
32. //解锁
33. lock.writeLock().unlock();
34. }
35. }
36. }
37.
38. public static void main(String[] args) {
39. final Example example = new Example();
40. new Thread(new Runnable() {
41. @Override
42. public void run() {
43. while (true){
44. example.read();
45. example.write();
46. }
47. }
48. }).start();
49. new Thread(new Runnable() {
50. @Override
51. public void run() {
52. while (true){
53. example.read();
54. example.write();
55. }
56. }
57. }).start();
58. }
59. }
运行结果:
根据结果可以发现,多线程下ReentrantReadWriteLock可以多线程同时读,但写的话同一时刻只有一个线程执行。
最后说一说读写锁的应用场景,我们可以利用读写锁可是实现一个多线程下数据缓存的功能,具体实现思路如下:
[java]
1. class dataCatch{
2. //缓存的数据
3. public volatile Boolean isCatch = false; //是否有缓存
4. new ReentrantReadWriteLock(); //生成读写锁
5.
6. public void process(){
7. //先加读锁,此时数据不会被修改
8. //数据没有缓存
9. if(!isCatch){
10. //解读锁
11. //加写锁,此时数据不会被读到
12. /********
13. *
14. * 执行数据查询操作并赋值给data
15. *
16. ********/
17. true;
18. //先加读锁后解写锁
19. lock.writeLock().lock();
20. }
21. /********
22. *
23. * 放回data数据给用户
24. *
25. ********/
26. //解读锁
27. }
28. }