资讯详情

Java JUC高并发编程(二)-集合&多线程锁

集合线程安全

1.1、List集合线程不安全演示

import java.util.ArrayList; import java.util.List; import java.util.UUID;  public class ThreadDemo4 {   public static void main(String[] args) {   List<String> list = new ArrayList<>();   for (int i = 0; i < 20; i  ) {    new Thread(()->{     list.add(UUID.randomUUID().toString().substring(0, 4));     System.out.println(list);    },String.valueOf(i)).start();   }  } }

执行异常:

1、Vector

2、Collections

3、CopyOnWriteArrayList

import java.util.*;  public class ThreadDemo4 {   public static void main(String[] args) {   List<String> list = new Vector<>();   for (int i = 0; i < 20; i  ) {    new Thread(()->{     list.add(UUID.randomUUID().toString().substring(0, 4));     System.out.println(list);    },String.valueOf(i)).start();   }  } }

import java.util.*;  public class ThreadDemo4 {   public static void main(String[] args) {   List<String> list = Collections.synchronizedList(new ArrayList<>());   for (int i = 0; i < 20; i  ) {    new Thread(()->{     list.add(UUID.randomUUID().toString().substring(0, 4));     System.out.println(list);    },String.valueOf(i)).start();   }  } }

import java.util.*; import java.util.concurrent.CopyOnWriteArrayList;  public class ThreadDemo4 {   public static void main(String[] args) {   List<String> list = new CopyOnWriteArrayList<>();   for (int i = 0; i < 20; i  ) {    new Thread(()->{     list.add(UUID.randomUUID().toString().substring(0, 4));     System.out.println(list);    },String.valueOf(i)).start();   }  } }

public class CopyOnWriteArrayList<E>     implements List<E>, RandomAccess, Cloneable, java.io.Serializable { ...     final transient ReentrantLock lock = new ReentrantLock();     private transient volatile Object[] array;     public CopyOnWriteArrayList() {         setArray(new Object[0]);     }     final void setArray(Object[] a) {         array = a;     }     public boolean add(E e) {         final ReentrantLock lock = this.lock;         lock.lock();         try {             Object[] elements = getArray();             int len = elements.length;             Object[] newElements = Arrays.copyOf(elements, len   1);             newElements[len] = e;             setArray(newElements);             return true;         } finally {             lock.unlock();         }     }

1.2、HashSet演示线程不安全

import java.util.*;  public class ThreadDemo4 {   public static void main(String[] args) {   Set<String> set = new HashSet<>();   for (int i = 0; i < 20; i  ) {    new Thread(()->{     set.add(UUID.randomUUID().toString().substring(0, 4));     System.out.println(set);    },String.valueOf(i)).start();   }  } }

执行异常:

解决方式:

1、CopyOnWriteArraySet

import java.util.*; import java.util.concurrent.CopyOnWriteArraySet;  public class ThreadDemo4 {   public static void main(String[] args) {   Set<String> set = new CopyOnWriteArraySet<>();   for (int i = 0; i < 20; i  ) {    new Thread(()->{     set.add(UUID.randomUUID().toString().substring(0, 4));     System.out.println(set);    },String.valueOf(i)).start();   }  } }

1.3、HashMap演示线程不安全

import java.util.*;  public class ThreadDemo4 {   public static void main(String[] args) {   Map<String,String> map = new HashMap<>();   for (int i = 0; i < 20; i  ) {    String key = String.valueOf(i);    new Thread(()->{     map.put(key,UUID.randomUUID().toString().substring(0, 4));     System.out.println(map);    },String.valueOf(i)).start();   }  } }

执行异常:

解决方式:

1、ConcurrentHashMap

import java.util.*; import java.util.cncurrent.ConcurrentHashMap;

public class ThreadDemo4 {

	public static void main(String[] args) {
		Map<String,String> map = new ConcurrentHashMap<>();
		for (int i = 0; i < 20; i++) {
			String key = String.valueOf(i);
			new Thread(()->{
				map.put(key,UUID.randomUUID().toString().substring(0, 4));
				System.out.println(map);
			},String.valueOf(i)).start();
		}
	}
}

二、多线程锁

Synchronized实现同步的基础:Java中每一个对象都可以作为锁。

1、对于普通同步方法,锁是当前实例对象。

2、对于静态同步方法,锁是当前类的class对象。

3、对于同步方法块,锁是Synchronized括号里配置的对象。

2.1、公平锁&非公平锁

public class ReentrantLock implements Lock, java.io.Serializable {
...
    public ReentrantLock() {
        sync = new NonfairSync();
    }

    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
...

    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

有的线程会饿死,优点是

阳光普照,效率比非公平锁低。公平锁会先去询问一下hasQueuedPredecessors()

2.2、可重入锁

Synchronized和Lock都是可重入锁。

例如:回到家里,只需要把家里的大门打开,家里的卧室门都不需要打开就能自由进入。这就是可重入的意思。

public class ThreadDemo5 {

	public static void main(String[] args) {
		Object obj = new Object();
		new Thread(()-> {
			synchronized(obj) {
				System.out.println(Thread.currentThread().getName()+" 外层");
				synchronized(obj) {
					System.out.println(Thread.currentThread().getName()+" 中层");
					synchronized(obj) {
						System.out.println(Thread.currentThread().getName()+" 内层");
					}
				}
			}
		},"t1").start();
	}
}
public class ThreadDemo5 {

	public synchronized void add() {
		add();
	}
	
	public static void main(String[] args) {
		new ThreadDemo5().add();
	}
}

执行上面出现:

2.3、死锁

两个或两个以上进程在执行过程中,因为争夺资源而造成一种相互等待的现象,如果没有外力干涉,他们无法再执行下去,这种现象被称为死锁。

1、系统资源不足

2、进程运行推进顺序不合适

3、资源分配不当

public class DeadLock {

	static Object a = new Object();
	static Object b = new Object();
	
	public static void main(String[] args) {
		new Thread(() ->{
			synchronized (a) {
				System.out.println(Thread.currentThread().getName() +"持有锁a,试图获取锁b");
				synchronized (b) {
					System.out.println(Thread.currentThread().getName() +"持有锁b");
				}
			}
		},"t1").start();
		new Thread(() ->{
			synchronized (b) {
				System.out.println(Thread.currentThread().getName() +"持有锁b,试图获取锁a");
				synchronized (a) {
					System.out.println(Thread.currentThread().getName() +"持有锁a");
				}
			}
		},"t2").start();
	}
}

1.JDK bin目录  jps.exe   

2.jstack 进程号

控制台上

--->jps -l   命令     

--->jstack 进程号

C:\Users\Administrator>jps -l
7748 com.lwz.study.day04.DeadLock
3768 jdk.jcmd/sun.tools.jps.Jps
5820

C:\Users\Administrator>jstack 7748
2022-04-05 14:08:27
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.202-b08 mixed mode):

"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000000002532800 nid=0x3600 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"t2" #12 prio=5 os_prio=0 tid=0x000000001a61d000 nid=0x3918 waiting for monitor entry [0x000000001afef000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.lwz.study.day04.DeadLock.lambda$1(DeadLock.java:21)
        - waiting to lock <0x00000000d5cbc010> (a java.lang.Object)
        - locked <0x00000000d5cbc020> (a java.lang.Object)
        at com.lwz.study.day04.DeadLock$$Lambda$2/135721597.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

"t1" #11 prio=5 os_prio=0 tid=0x000000001a61b800 nid=0x2a48 waiting for monitor entry [0x000000001aeef000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.lwz.study.day04.DeadLock.lambda$0(DeadLock.java:13)
        - waiting to lock <0x00000000d5cbc020> (a java.lang.Object)
        - locked <0x00000000d5cbc010> (a java.lang.Object)
        at com.lwz.study.day04.DeadLock$$Lambda$1/531885035.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x00000000198c8800 nid=0xc5c runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #9 daemon prio=9 os_prio=2 tid=0x000000001983a000 nid=0x3834 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x000000001982e000 nid=0x10f8 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x000000001982a000 nid=0x114 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x000000001981f000 nid=0x1c64 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001981c800 nid=0x3bac waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x00000000197c8800 nid=0x1ce4 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x00000000197b1800 nid=0x8b4 in Object.wait() [0x0000000019d8f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d5c08ed0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
        - locked <0x00000000d5c08ed0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x00000000197b0800 nid=0x9c8 in Object.wait() [0x0000000019c8e000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d5c06bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x00000000d5c06bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=2 tid=0x00000000179b9800 nid=0x3b90 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002547800 nid=0x3174 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002549000 nid=0x3220 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x000000000254a800 nid=0x828 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x000000000254c000 nid=0x528 runnable

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x000000000254f800 nid=0x498 runnable

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x0000000002550800 nid=0x1344 runnable

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x0000000002554000 nid=0x1294 runnable

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x0000000002555000 nid=0x1be4 runnable

"VM Periodic Task Thread" os_prio=2 tid=0x00000000198ee800 nid=0xcb0 waiting on condition

JNI global references: 310


Found one Java-level deadlock:
=============================
"t2":
  waiting to lock monitor 0x000000000262bc08 (object 0x00000000d5cbc010, a java.lang.Object),
  which is held by "t1"
"t1":
  waiting to lock monitor 0x000000000262e6a8 (object 0x00000000d5cbc020, a java.lang.Object),
  which is held by "t2"

Java stack information for the threads listed above:
===================================================
"t2":
        at com.lwz.study.day04.DeadLock.lambda$1(DeadLock.java:21)
        - waiting to lock <0x00000000d5cbc010> (a java.lang.Object)
        - locked <0x00000000d5cbc020> (a java.lang.Object)
        at com.lwz.study.day04.DeadLock$$Lambda$2/135721597.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)
"t1":
        at com.lwz.study.day04.DeadLock.lambda$0(DeadLock.java:13)
        - waiting to lock <0x00000000d5cbc020> (a java.lang.Object)
        - locked <0x00000000d5cbc010> (a java.lang.Object)
        at com.lwz.study.day04.DeadLock$$Lambda$1/531885035.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

Java JUC高并发编程(一)

Java JUC高并发编程(三)-Callable&JUC辅助类

标签: 24bc08集成电路ic

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台