JAVA多线程--2 锁

 

多线程访问资源时,如果没有做处理,很容易出现资源错乱,必须通过锁机制实现资源共享 例如:
《JAVA多线程--2 锁》
《JAVA多线程--2 锁》
View Code
 1 
package multithread;

 2 
import java.util.HashMap;

 3 
import java.util.Map;

 4 
import java.util.concurrent.ConcurrentHashMap;

 5 
import java.util.concurrent.ExecutorService;

 6 
import java.util.concurrent.Executors;

 7 
public 
class NoLockDemo {

 8 
public 
static 
void main(String[] args) 
throws InterruptedException {

 9 NoLockDemo ld=
new NoLockDemo();

10 ExecutorService exec=Executors.newFixedThreadPool(5);

11 TestNumber t=ld.
new TestNumber();

12 
for(
int i=0;i<50;i++){

13 exec.execute(t);

14 }

15 }

16 
class TestNumber 
extends Thread{

17 
int num=0;

18 Map<Integer, Integer> map=
new HashMap<Integer, Integer>();

19 Map<Integer, Integer> correntmap=
new ConcurrentHashMap<Integer, Integer>();

20 
public TestNumber(){

21 }

22 
public 
int addNum(){

23 num++;

24 num++;

25 
//
map.put(num, num);


26 
correntmap.put(num, num);

27 
return num;

28 }

29 
public 
void run(){

30 setName(“test-“);

31 addNum(); 

32 System.out.println(num);

33 
//
System.out.println(map);


34 
System.out.println(correntmap);

35 }

36 } 

37 } 结果:
6
6
6
8
10
{6=6, 8=8, 2=6, 10=10, 4=6}
{6=6, 8=8, 2=6, 10=10, 4=6} … 其中。
2=6, 10=10, 4=6 ,对于我们程序来说 correntmap.put(num, num);不应该有这样的结果,但是这样错乱的结果产生了,并且是多线程访问资源导致 而如果我们使用HashMap而不用ConcurrentHashMap,就会报错: Exception in thread “pool-1-thread-5” java.util.ConcurrentModificationException 因此在多线程操作中,尽量使用concurrent包下的类 如何解决此类问题? 通过关键字synchronized或者Lock实现资源竞争访问。 对于他们的总结如下: * @author Administrator * 1、synchronized可用于方法、对象、static方法 * synchronized method 锁对象就是本身对象,同synchroniezd(this){}; * synchronized(obj) 其中obj就是一个对象,只是实现了一个同步的代码块,使用byte obj=new byte[0]优化 * synchronized static method 锁对象类对象,同synchronized(Foo.class) * * 2、与Lock的区别 * synchronized:所有对象都自动含有单一锁,jvm负责跟踪锁次数,无需人工干预。锁的获取释放在同一模块,并且相反顺序 * Lock:基于栈中的框架而不是某个具体的对象,需要设置锁的开始和结束。可以提供无条件的、可轮询的、定时的、可中断的锁获取操作。 * 例如: 《JAVA多线程--2 锁》 《JAVA多线程--2 锁》 View Code   1  public  class LockDemo {
  2  public  static  void main(String[] args)  throws InterruptedException {
  3 LockDemo ld= new LockDemo();
  4 ExecutorService exec=Executors.newFixedThreadPool(5);
  5 TestNumber t=ld. new TestNumber();
  6  for( int i=0;i<50;i++){
  7  exec.execute(t);
  8 }
  9  // exec.shutdown();
 10  final AttemptingLock alock=ld. new AttemptingLock();
 11 alock.untimed();
 12 alock.timed();
 13  new Thread(){
 14 {
 15 setDaemon( true);
 16 setName(“test attemptinglock”);
 17 }
 18  public  void run(){
 19  while( true){
 20 alock.lock.lock();
 21 }
 22 }
 23 }.start();
 24 Thread.sleep(1000);
 25 alock.untimed();
 26 alock.timed();
 27 exec.shutdown();
 28 }
 29  class AttemptingLock {
 30  private ReentrantLock lock= new ReentrantLock();
 31  public  void untimed(){
 32  boolean captured=lock.tryLock();
 33 System.out.println(“captured:”+captured);
 34  if(captured){
 35 lock.unlock();
 36 }
 37 }
 38  public  void timed(){
 39  boolean captured =  false;
 40  try {
 41 captured = lock.tryLock(2,TimeUnit.SECONDS);
 42 System.out.println(“timed captured:”+captured);
 43 }  catch (InterruptedException e) {
 44  //  TODO Auto-generated catch block
 45  e.printStackTrace();
 46 } finally{
 47  if(captured){
 48 lock.unlock();
 49 }
 50 }
 51 }
 52 }
 53  class TestNumber  extends Thread{
 54  int num=0;
 55 Map<Integer, Integer> map= new HashMap<Integer, Integer>();
 56 Map<Integer, Integer> correntmap= new ConcurrentHashMap<Integer, Integer>();
 57  private Lock lock= new ReentrantLock();
 58  // byte 优于Object Object obj=new Object();
 59  private  byte[] obj= new  byte[0];
 60  public TestNumber(){
 61 }
 62  public  synchronized  int addNum(){
 63 num++;
 64 num++;
 65  // map.put(num, num);
 66  correntmap.put(num, num);
 67  return num;
 68 }
 69  public  int addNumSyschronizedObject(){
 70  synchronized (obj) {
 71 num++;
 72 num++;
 73 correntmap.put(num, num);
 74  return num;
 75 }
 76  /*  同方法同步
 77  synchronized(this){
 78  num++;
 79  num++;
 80  correntmap.put(num, num);
 81  return num;
 82  }
 83  */
 84 }
 85  public  int lockAddNum(){
 86 lock.lock();
 87  try{
 88 num++;
 89 num++;
 90  // map.put(num, num);
 91  correntmap.put(num, num);
 92 } finally{
 93 lock.unlock();
 94 }
 95  return num;
 96 }
 97  public  void run(){
 98 setName(“test-“);
 99  // addNum();
100  lockAddNum();
101 System.out.println(num);
102  // System.out.println(map);
103  System.out.println(correntmap);
104 }
105 }
106  static  class Test2{
107  private  static  int num=0;
108  public  synchronized  static  int getNum(){
109  return num++;
110 }
111 }
112 }
结果: captured:true timed captured:true 88 {40=40, 22=22, 12=12, 96=96, 20=20, 6=6, 68=68, 62=62, 48=48, 34=34, 28=28, 42=42, 18=18, 88=88, 74=74, 56=56, 84=84, 98=98, 46=46, 70=70, 90=90, 36=36, 26=26, 8=8, 82=82, 72=72, 100=100, 54=54, 2=2, 86=86, 44=44, 58=58, 78=78, 92=92, 64=64, 16=16, 30=30, 10=10, 52=52, 38=38, 80=80, 24=24, 60=60, 14=14, 94=94, 66=66, 32=32, 4=4, 76=76, 50=50} {40=40, 22=22, 12=12, 96=96, 20=20, 6=6, 68=68, 62=62, 48=48, 34=34, 28=28, 42=42, 18=18, 88=88, 74=74, 56=56, 84=84, 98=98, 46=46, 70=70, 90=90, 36=36, 26=26, 8=8, 82=82, 72=72, 100=100, 54=54, 2=2, 86=86, 44=44, 58=58, 78=78, 92=92, 64=64, 16=16, 30=30, 10=10, 52=52, 38=38, 80=80, 24=24, 60=60, 14=14, 94=94, 66=66, 32=32, 4=4, 76=76, 50=50} captured:false timed captured:false 此时不会出现刚才那种错乱 Lock可以通过tryLock方法判断是否可以获取锁,当不能获取时可以进行处理,同时tryLock方法可以设置超时时间。 对于Lock必须显式的调用lock()方法与unlock()方法进行释放。使用Lock更加灵活。  
 总结: 1、通常Lock会比synchronized高效 2、使用synchronized–只互斥那些你绝对必须互斥的部分 3、synchronized的代码可读性比较高 4、Atomic对象只能处理比较简单的情况,包括你只有一个要被修改的Atomic对象,并且独立于其他对象。

 

    原文作者:wasp
    原文地址: https://www.cnblogs.com/wasp520/archive/2012/06/23/2559425.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞