并发编程——java线程基础之线程同步

实现java线程同步的主要方法

  • synchronized关键字
  • 可重入锁

synchronized的应用

  synchronized可以修饰代码块和方法,对代码块的加锁范围可以是类级别和对象级别,方法加锁本质上是对象级别加锁。

  对象级别加锁

 1 package base.synchronize;
 2 
 3 public class Thread1 implements Runnable{
 4     private Object obj;
 5     
 6     public Thread1(Object obj) {
 7         this.obj = obj;
 8     }
 9 
10     @Override
11     public void run() {
12         synchronized (obj) {
13             System.out.println(Thread.currentThread().getName() + ": start...");
14             try {
15                 Thread.sleep(10 * 1000);
16             } catch (InterruptedException e) {
17                 // TODO Auto-generated catch block
18                 e.printStackTrace();
19             }
20             System.out.println(Thread.currentThread().getName() + ": end!");
21         }
22     }
23 
24 }
对象级别加锁线程类
 1 package base.synchronize;
 2 
 3 import org.junit.Test;
 4 
 5 public class SynchronizeObject {
 6     public Object obj = new Object();
 7     
 8     @Test
 9     public void testFunc() {
10         Thread t1 = new Thread(new Thread1(obj), "t1");
11         Thread t2 = new Thread(new Thread1(obj), "t2");
12         
13         t1.start();
14         t2.start();
15         
16         try {
17             t1.join();
18             t2.join();
19         } catch (InterruptedException e) {
20             e.printStackTrace();
21         }
22     }
23 }
客户端

  类级别加锁

 1 package base.synchronize;
 2 
 3 public class Thread2 implements Runnable{
 4 
 5     @Override
 6     public void run() {
 7         synchronized (Thread2.class) {
 8             System.out.println(Thread.currentThread().getName() + ": start...");
 9             try {
10                 Thread.sleep(10 * 1000);
11             } catch (InterruptedException e) {
12                 // TODO Auto-generated catch block
13                 e.printStackTrace();
14             }
15             System.out.println(Thread.currentThread().getName() + ": end!");
16         }
17     }
18 
19 }
类级别加锁线程类
 1 package base.synchronize;
 2 
 3 import org.junit.Test;
 4 
 5 public class SynchronizeClass {    
 6     @Test
 7     public void testFunc() {
 8         Thread t1 = new Thread(new Thread2(), "t1");
 9         Thread t2 = new Thread(new Thread2(), "t2");
10         
11         t1.start();
12         t2.start();
13         
14         try {
15             t1.join();
16             t2.join();
17         } catch (InterruptedException e) {
18             e.printStackTrace();
19         }
20     }
21 }
客户端

  方法级别加锁

 1 package base.synchronize;
 2 
 3 public class Thread3 implements Runnable{
 4 
 5     @Override
 6     public void run() {
 7         function();
 8     }
 9     
10     public synchronized void function() {
11         System.out.println(Thread.currentThread().getName() + ": start...");
12         try {
13             Thread.sleep(10 * 1000);
14         } catch (InterruptedException e) {
15             // TODO Auto-generated catch block
16             e.printStackTrace();
17         }
18         System.out.println(Thread.currentThread().getName() + ": end!");
19     }
20 
21 }
方法级别加锁线程类
 1 package base.synchronize;
 2 
 3 import org.junit.Test;
 4 
 5 public class SynchronizeFunc {
 6     @Test
 7     public void testFunc() {
 8         Thread3 t = new Thread3();
 9         Thread t3 = new Thread(t, "t3");
10         Thread t4 = new Thread(t, "t4");
11         
12         t3.start();
13         t4.start();
14         
15         try {
16             t3.join();
17             t4.join();
18         } catch (InterruptedException e) {
19             e.printStackTrace();
20         }
21     }
22 }
客户端

可重入锁的应用

  可重入锁(ReentrantLock)含义是,当一个线程获取了某一个可重入锁后可以再次去获取该可重入锁。其中分为普通的可重入锁以及读写锁。

  可重入锁的使用

 1 package base.lock;
 2 
 3 import java.util.concurrent.locks.ReentrantLock;
 4 
 5 public class Thread1 implements Runnable{
 6     private ReentrantLock lock;
 7     
 8     public Thread1(ReentrantLock lock) {
 9         this.lock = lock;
10     }
11 
12     @Override
13     public void run() {
14         lock.lock();
15         System.out.println(Thread.currentThread().getName() + ": start...");
16         try {
17             Thread.sleep(5 * 1000);
18         } catch (InterruptedException e) {
19             // TODO Auto-generated catch block
20             e.printStackTrace();
21         }
22         System.out.println(Thread.currentThread().getName() + ": end.");
23         lock.unlock();
24     }
25 
26 }
添加可重入锁的线程类
 1 package base.lock;
 2 
 3 import java.util.concurrent.locks.ReentrantLock;
 4 
 5 import org.junit.Test;
 6 
 7 public class LockMain {
 8     ReentrantLock lock = new ReentrantLock();
 9     
10     @Test
11     public void testCase() throws InterruptedException {
12         Thread1 runnable = new Thread1(lock);
13         Thread t1 = new Thread(runnable, "t1");
14         Thread t2 = new Thread(runnable, "t2");
15         
16         t1.start();
17         t2.start();
18         
19         t1.join();
20         t2.join();
21     }
22 }
客户端

  读写锁的使用

  读写锁,可以使用更细粒度的锁。读写锁的原则,读读共享、读写互斥、写写互斥。并且当有一个线程获取到了读锁且有一个线程获取写锁阻塞时,后来的读锁一定排队在该写锁之后才能获取资源,这是为了防止饥饿现象的发生(多运行几次读写混合客户端,观察不同的执行结果,分析执行结果不同的原因)

 1 package base.lock.readwritelock;
 2 
 3 import java.util.concurrent.locks.ReentrantReadWriteLock;
 4 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
 5 
 6 public class Thread1 implements Runnable{
 7     private ReentrantReadWriteLock lock;
 8     
 9     public Thread1(ReentrantReadWriteLock lock) {
10         this.lock = lock;
11     }
12 
13     @Override
14     public void run() {
15         WriteLock writeLock = lock.writeLock();
16         writeLock.lock();
17         System.out.println(Thread.currentThread().getName() + ": 写数据start...");
18         try {
19             Thread.sleep(5 * 1000);
20         } catch (InterruptedException e) {
21             // TODO Auto-generated catch block
22             e.printStackTrace();
23         }
24         System.out.println(Thread.currentThread().getName() + ": 写数据end.");
25         writeLock.unlock();
26 
27     }
28 
29 }
写数据线程类
 1 package base.lock.readwritelock;
 2 
 3 import java.util.concurrent.locks.ReentrantReadWriteLock;
 4 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
 5 
 6 public class Thread2 implements Runnable{
 7     private ReentrantReadWriteLock lock;
 8     
 9     public Thread2(ReentrantReadWriteLock lock) {
10         this.lock = lock;
11     }
12 
13     @Override
14     public void run() {
15         ReadLock readLock = lock.readLock();
16         readLock.lock();
17         System.out.println(Thread.currentThread().getName() + ": 读数据start...");
18         try {
19             Thread.sleep(5 * 1000);
20         } catch (InterruptedException e) {
21             // TODO Auto-generated catch block
22             e.printStackTrace();
23         }
24         System.out.println(Thread.currentThread().getName() + ": 读数据end.");
25         readLock.unlock();
26 
27     }
28 
29 }
读数据线程类
 1 package base.lock.readwritelock;
 2 
 3 import java.util.concurrent.locks.ReentrantReadWriteLock;
 4 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
 5 
 6 public class Thread2 implements Runnable{
 7     private ReentrantReadWriteLock lock;
 8     
 9     public Thread2(ReentrantReadWriteLock lock) {
10         this.lock = lock;
11     }
12 
13     @Override
14     public void run() {
15         ReadLock readLock = lock.readLock();
16         readLock.lock();
17         System.out.println(Thread.currentThread().getName() + ": 读数据start...");
18         try {
19             Thread.sleep(5 * 1000);
20         } catch (InterruptedException e) {
21             // TODO Auto-generated catch block
22             e.printStackTrace();
23         }
24         System.out.println(Thread.currentThread().getName() + ": 读数据end.");
25         readLock.unlock();
26 
27     }
28 
29 }
纯写客户端
 1 package base.lock.readwritelock;
 2 
 3 import java.util.concurrent.locks.ReentrantLock;
 4 import java.util.concurrent.locks.ReentrantReadWriteLock;
 5 
 6 import org.junit.Test;
 7 
 8 public class ReadLockMain {
 9     ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
10     
11     @Test
12     public void testCase() throws InterruptedException {
13         
14         Thread2 runnable = new Thread2(lock);
15         Thread t1 = new Thread(runnable, "t1");
16         Thread t2 = new Thread(runnable, "t2");
17 
18         t1.start();
19         t2.start();
20         
21         t1.join();
22         t2.join();
23     }
24 }
纯读客户端
 1 package base.lock.readwritelock;
 2 
 3 import java.util.concurrent.locks.ReentrantReadWriteLock;
 4 
 5 import org.junit.Test;
 6 
 7 public class ReadWriteLockMain {
 8     ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
 9     
10     @Test
11     public void testCase() throws InterruptedException {
12         
13         Thread1 runnable1 = new Thread1(lock);
14         Thread2 runnable2 = new Thread2(lock);
15         Thread t1 = new Thread(runnable1, "t1");
16         Thread t2 = new Thread(runnable2, "t2");
17         Thread t3 = new Thread(runnable2, "t3");
18 
19         t2.start();
20         t1.start();
21         t3.start();
22 
23         
24         t1.join();
25         t2.join();
26         t3.join();
27     }
28 }
读写混合客户端

 

posted @ 2018-01-10 15:38  从“灵”开始  阅读(160)  评论(0编辑  收藏  举报