java多线程基本概述——Lock

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java多线程基本概述——Lock相关的知识,希望对你有一定的参考价值。

公平锁与非公平锁:公平锁代表获取锁的顺序时按照加入锁的顺序来分配的,即按照FIFO(first in first out)的顺序来的,而非公平锁就时一种抢占式,是随机分配的。不一定先到先地。这就有可能导致某些线程一致获取不到锁。

package soarhu;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class TestNum {
  private Lock lock ;

    public TestNum(boolean fair) {
        lock = new ReentrantLock(fair);

    }

    public void test(){
          lock.lock();
      try {
          System.out.println(Thread.currentThread().getName()+"  lock ");
      } finally {
          lock.unlock();
      }
  }

}
public class Test{
    public static void main(String[] args)  {
        TestNum t = new TestNum(true);
        for (int i = 0; i < 5; i++) {
            new Thread(){
                @Override
                public void run() {
                    t.test();
                    System.out.println(Thread.currentThread().getName()+" get lock ");
                }
            }.start();
        }
    }
}

输出结果:

Thread-0  lock 
Thread-1  lock 
Thread-0 get lock 
Thread-1 get lock 
Thread-3  lock 
Thread-3 get lock 
Thread-2  lock 
Thread-2 get lock 
Thread-4  lock 
Thread-4 get lock 

Process finished with exit code 0

如果改为:

public class Test{
    public static void main(String[] args)  {
        TestNum t = new TestNum(false);
        for (int i = 0; i < 5; i++) {
            new Thread(){
                @Override
                public void run() {
                    t.test();
                    System.out.println(Thread.currentThread().getName()+" get lock ");
                }
            }.start();
        }
    }
}

输出结果:

Thread-0  lock 
Thread-2  lock 
Thread-2 get lock 
Thread-0 get lock 
Thread-1  lock 
Thread-1 get lock 
Thread-4  lock 
Thread-4 get lock 
Thread-3  lock 
Thread-3 get lock 

Process finished with exit code 0

可见不是按照FIFO来进行分配地。

getHoldCount()、getQueueLength()、getWaitQueLength()、hasQueuedThread()、hasQueuedThreads()、hasWatiers().

1>getHoldCount()表示查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。

package soarhu;

import java.util.concurrent.locks.ReentrantLock;

class TestNum {
    private ReentrantLock lock ;

    public TestNum(boolean fair) {
        lock = new ReentrantLock(fair);

    }

    public void test(){
        System.out.println("enter test getHoldCount="+lock.getHoldCount());
          lock.lock();
      try {
          System.out.println("try test getHoldCount="+lock.getHoldCount());
          test2();
      } finally {
          System.out.println("test before finish getHoldCount="+lock.getHoldCount());
          lock.unlock();
          System.out.println("test after finish getHoldCount="+lock.getHoldCount());
      }
    }

    public void test2(){
        System.out.println("enter test2 getHoldCount="+lock.getHoldCount());
        lock.lock();
        try {
            System.out.println("try test2 getHoldCount="+lock.getHoldCount());
        } finally {
            System.out.println("test2 before finish getHoldCount="+lock.getHoldCount());
            lock.unlock();
            System.out.println("test2 after finish getHoldCount="+lock.getHoldCount());
        }
    }

}
public class Test{
    public static void main(String[] args)  {
        TestNum t = new TestNum(false);
        t.test();
    }
}

输出结果:

enter test getHoldCount=0
try test getHoldCount=1
enter test2 getHoldCount=1
try test2 getHoldCount=2
test2 before finish getHoldCount=2
test2 after finish getHoldCount=1
test before finish getHoldCount=1
test after finish getHoldCount=0

Process finished with exit code 0

2>getQueueLength()表示查询等待获取此锁定的大概个数。api:

public final int getQueueLength()
Returns an estimate of the number of threads waiting to acquire this lock.
The value is only an estimate because the number of threads may change dynamically while this method traverses internal data structures.
This method is designed for use in monitoring of the system state, not for synchronization control. ------------------------------------------------------------------------------ 返回等待获取的线程数的估计数。该值只是一个估计,因为线程数可能会在此方法遍历内部数据结构时动态更改。该方法设计用于监控系统状态,不用于同步控制。

例子:

package soarhu;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

class TestNum {
    public final ReentrantLock lock ;

    public TestNum(boolean fair) {
        lock = new ReentrantLock(fair);

    }

    public void test(){
          lock.lock();
      try {
          System.out.println(Thread.currentThread().getName()+"Enter");
          //Thread.sleep(Integer.MAX_VALUE);
          lock.lock();
      } catch (Exception e) {
          e.printStackTrace();
      } finally {
          lock.unlock();
      }
    }

}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        TestNum t = new TestNum(false);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                t.test();
            }
        };
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(runnable);
        }
        for (int i = 0; i < 10; i++) {
            threads[i].start();
        }
        TimeUnit.SECONDS.sleep(2);
        System.out.println("holdCont="+t.lock.getHoldCount()+"  queueLength="+t.lock.getQueueLength());
        threads[2].stop();
        TimeUnit.SECONDS.sleep(8);
        System.out.println("holdCont="+t.lock.getHoldCount()+"  queueLength="+t.lock.getQueueLength());
    }
}

输出结果:

Thread-0Enter
holdCont=0  queueLength=9
holdCont=0  queueLength=8

Process finished with exit code 1

3>getQueueLength(Conditon condition)表示返回等待与此锁定相关给定条件的Condition的线程估计数。api:

Returns an estimate of the number of threads waiting on the given condition associated with this lock. Note that because timeouts and interrupts may occur at any time, the estimate serves only as an upper bound on the actual number of waiters. This method is designed for use in monitoring of the system state, not for synchronization control.
----------------------------------------------
返回与此锁相关联的给定条件等待的线程数的估计。 请注意,由于超时和中断可能在任何时间发生,估计仅作为实际服务员人数的上限。 该方法设计用于监视系统状态,不用于同步控制。
package soarhu;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class TestNum {
     final ReentrantLock lock = new ReentrantLock(true);
    private Condition condition = lock.newCondition();

     TestNum(boolean fair) {
        super();
    }

     void test() {
          lock.lock();
      try {
          condition.await();
      } catch (Exception e) {
          e.printStackTrace();
      } finally {
          lock.unlock();
      }
    }

    void test2() throws InterruptedException {
        lock.lock();

        try {
            System.out.println("count="+lock.getWaitQueueLength(condition));
            condition.signal();
            System.out.println("count="+lock.getWaitQueueLength(condition));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        TestNum t = new TestNum(false);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                t.test();
            }
        };
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(runnable);
        }
        for (int i = 0; i < 10; i++) {
            threads[i].start();
        }
        TimeUnit.SECONDS.sleep(2);
        System.out.println("holdCont="+t.lock.getHoldCount()+"  queueLength="+t.lock.getQueueLength());
        t.test2();
    }
}

输出结果:

holdCont=0  queueLength=0
count=10
count=9

4>hasQueuedThread(Thread thread)表示查询指定的线程是否正在等待获取此锁定。api:

public final boolean hasQueuedThread(Thread thread)
Queries whether the given thread is waiting to acquire this lock. Note that because cancellations may occur at any time, a true return does not guarantee that this thread will ever acquire this lock. This method is designed primarily for use in monitoring of the system state.
---------------------------------------------------------------
查询给定线程是否等待获取此锁。 请注意,由于取消可能会在任何时候发生,真正的返回并不能保证此线程将获得此锁。 该方法主要用于监视系统状态。

例子:

package soarhu;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class TestNum {
    public final ReentrantLock lock = new ReentrantLock(true);
    private Condition condition = lock.newCondition();

     TestNum(boolean fair) {
        super();
    }

     void test() {
          lock.lock();
      try {
          Thread.sleep(Integer.MAX_VALUE);
      } catch (Exception e) {
          e.printStackTrace();
      } finally {
          lock.unlock();
      }
    }

    void test2() throws InterruptedException {
        lock.lock();

        try {
            System.out.println("count="+lock.getWaitQueueLength(condition));
            condition.signal();
            System.out.println("count="+lock.getWaitQueueLength(condition));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        TestNum t = new TestNum(false);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                t.test();
            }
        };
        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        t1.start();
        Thread.sleep(500);
        t2.start();
        System.out.println("t1   "+t.lock.hasQueuedThread(t1));
        System.out.println("t2   "+t.lock.hasQueuedThread(t2));
        System.out.println("is?  "+t.lock.hasQueuedThreads());
    }
}

输出结果:

t1   false
t2   true
is?  true

Process finished with exit code 1

5>hasWaiters(Condition condition)表示查询是否有线程正在等待此锁定有关的Condition。api:

Queries whether any threads are waiting on the given condition associated with this lock. Note that because timeouts and interrupts may occur at any time, a true return does not guarantee that a future signal will awaken any threads. This method is designed primarily for use in monitoring of the system state.
--------------------------------------------------------------------
查询任何线程是否等待与此锁相关联的给定条件。 请注意,由于超时和中断可能在任何时候发生,真正的返回并不能保证未来的信号将唤醒任何线程。 该方法主要用于监视系统状态。
package soarhu;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class TestNum {
    final ReentrantLock lock = new ReentrantLock(true);
    private Condition condition = lock.newCondition();

    TestNum(boolean fair) {
        super();
    }

    void test() {
        lock.lock();
        try {
            condition.await();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    void test2() throws InterruptedException {
        lock.lock();

        try {
            System.out.println("waitQueueLength count="+lock.getWaitQueueLength(condition)+
                                "  hasWaiters?"+lock.hasWaiters(condition));
            condition.signal();
            System.out.println("waitQueueLength count="+lock.getWaitQueueLength(condition)+
                                "  hasWaiters?"+lock.hasWaiters(condition));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        TestNum t = new TestNum(false);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                t.test();
            }
        };
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(runnable);
        }
        for (int i = 0; i < 10; i++) {
            threads[i].start();
        }
        TimeUnit.SECONDS.sleep(2);
        System.out.println("holdCont="+t.lock.getHoldCount()+"  queueLength="+t.lock.getQueueLength());
        t.test2();
    }
}

输出结果:

holdCont=0  queueLength=0
waitQueueLength count=10  hasWaiters?true
waitQueueLength count=9  hasWaiters?true

Process finished with exit code 1

 



以上是关于java多线程基本概述——Lock的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程——Lock&Condition

Java多线程与并发库高级应用-工具类介绍

Java并发线程通信

Java多线程安全原子性之AtomicCASSynchronized和Lock

Java多线程概述及创建

Java多线程与并发库高级应用-工具类介绍