java 多线程加锁-锁住了什么?

一 、常用的 两种 加锁方法

1、关键字 synchronized
2、ReentrantLock

官方ReentranLock 源码描述: A reentrant mutual exclusion {@link Lock} with the same basic behavior and semantics as the implicit monitor lock accessed using{@code synchronized} methods and statements, 
but with extended capabilities.

翻译就是:

 ReentranLock 具有与使用{@code synchronized}方法和语句访问的隐式监视锁相同的基本行为和语义的可重入互斥 但具有扩展功能。


二、锁住了什么?

1、synchronized 

  (1)  测试 2 个线程 ,执行任务时,Runnable 加锁  synchronized( this )或 synchronized(LockRunnable.this)  => 当前访问 该 函数 的对象

  1.   接受 相同的 Runnabnle  ==》 互斥顺序执行 
    0 :---start name{}Thread-0
    2065426428
    1 : --- end name{} Thread-0
    1 :---start name{}Thread-1
    2065426428
    2 : --- end name{} Thread-1 
  2.   接受不同的  Runnabnle  ==》同时执行,
0 :---start name{}Thread-0 
0 :---start name{}Thread-1

   2065426428
2065426428
1 : --- end name{} Thread-0
1 : --- end name{} Thread-1


       3、锁在 方法    private syschronzied void print(){ .... }
 (1 )  接受 相同的 Runnable  ==> 互斥顺序执行 
( 2)  接受 不同的 Runnable  ==>  同时执行

synchronized( this )

当线程接受的 Runnable 回调函数 不同时,出现 加锁无效的状况, 原因是  只是锁住的 是 this ( 当前对象 ),当 对象不一致时,锁好像 “失效了”


synchronized(类的静态变量时), 每个线程共享的内存变量,指向同一块内存区

在这里 是 

synchronized (lockObj)

3、  接受不同的  Runnabnle  ==》 互斥顺序执行, 打印的 lockObj 对象的hashcode 相同
 0 :---start name{}Thread-0
799125565 #
1 : --- end name{} Thread-0
0 :---start name{}Thread-1
799125565
1 : --- end name{} Thread-1

syschronzied ( 变量) 锁住变量 锁的是  一个 指针,该指针执行 变量的内存区的头指针。

分配的内存区相同,即指针相同,例如 类的静态变量(存储在 多线程共享的内存区--》方法区 ,jvm 内存分配 )
this 关键词 当 多个 线程 接受 同一个对象时,既内存已经分派,同一块内存区 ,本质上是 每个线程都有自己的拷贝指针,但是 this 的 指针 相同,同理 接受不同的对象,不同的内存,不同的指针,锁住的不是同一个“地方”

  private syschronzied void print(){ .... } 同理,锁在 不同对象的  同一个 方法上,虽然方法名相同,但是对象不同,对象的内存区不同,访问对象的  方法的 程序计数器 也不同(每个线程独有的内存区叫程序计数器
  • (2)当被阻塞的线程 去哪了?
  • 各自保存自己的程序执行到哪里),锁住的 不是同一个“地方”

  • 2、ReentranLock 锁住了什么?

  • 多个线程接受 不同的 runnable 时,使用 ReentranLock 也得是 静态的 static 

    • 1 、在保证 是 同一个 ReentranLock 对象时,查看 lock.lock()操作源码,通过控制获取线程安全的变量state互斥,实现了锁住一个 方法流程,
    •  -- 实现类是 NonfairSync, (1)计数,同一个线程下锁定的次数,可以实现多层锁定,unlock是 使状态值减少,state 变为0时,表示已经没有线程访问了
    • ,final void lock() {
          if (compareAndSetState(0, 1))
              setExclusiveOwnerThread(Thread.currentThread());
          else
              acquire(1);
      }

  • 2、线程获取锁
    final boolean nonfairTryAcquire(int acquires) {
        final Thread current = Thread.currentThread(); // 当前 线程
        int c = getState(); // 保存的 状态值 ,可以累加
        if (c == 0) { // 当前没有 线程获取
            if (compareAndSetState(0, acquires)) { // 线程安全设置 1,并保存 当前访问的线程,
                setExclusiveOwnerThread(current);
                return true; 
            }
        }
        else if (current == getExclusiveOwnerThread()) { // state>0 表示已经有线程访问了,如果是 第一次访问的线程
            int nextc = c + acquires; // 访问次数++,既是 锁的次数加,并保存次数
            if (nextc < 0) // overflow
                throw new Error("Maximum lock count exceeded");
            setState(nextc); 
            return true;
        }
        return false;
    }
3、当被阻塞的线程去哪了? state >0  && 不是保存的 那个线程 
构造一个Node 数据结构,加入了 等待队列,不间断的在 等待队列中 获取 线程 ,来获取 锁,没获得锁 ,自行中断


private Node addWaiter(Node mode) {
    Node node = new Node(Thread.currentThread(), mode);
    // Try the fast path of enq; backup to full enq on failure
    Node pred = tail;
    if (pred != null) {
        node.prev = pred;
        if (compareAndSetTail(pred, node)) {
            pred.next = node;
            return node;
        }
    }
    enq(node);
    return node;
}
/**
 * Acquires in exclusive uninterruptible mode for thread already in
 * queue. Used by condition wait methods as well as acquire.
 *
 * @param node the node
 * @param arg the acquire argument
 * @return {@code true} if interrupted while waiting
 */
final boolean acquireQueued(final Node node, int arg) {
    boolean failed = true;
    try {
        boolean interrupted = false;
        for (;;) {
            final Node p = node.predecessor();
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null; // help GC
                failed = false;
                return interrupted;
            }
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                interrupted = true;
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}


public class LockRunable implements Runnable {

    Integer count = 0;
    private static  final  ReentrantLock lock = new ReentrantLock( );
    private static  final  Condition condThree  = lock.newCondition();
    private static  final  Condition condSix = lock.newCondition();

    private static  Object lockObj = new Object();

    public static ReentrantLock getLock() {
        return lock;
    }

    @Override
    public void run() {
        synchronized ( lockObj ){

//        lock.lock();

        try {

            System. out.println(count + " :---start name{}" + Thread.currentThread().getName() );
            System.out.println( lockObj.hashCode() );
            Thread.currentThread().sleep( 400 ); // 模拟执行一个耗时的任务
//            while ( count <=3 ){
                count ++;
//            }
            System.out.println(  );
//            try {

        
public static void main(String[] args) {

    Runnable runnable1 = new LockRunable();
    Runnable runnable =  new LockRunable();
  
    // 接受同一个 回调函数
    Thread threadOne = new Thread(  runnable );
    Thread threadTwo = new Thread(  runnable );
    Thread threadTwo = new Thread(  runnable1 ); // 第二次 测试
threadOne.start() ; threadTwo.start() ;

  

   @Override
    public void run() {
        synchronized ( this ){

//        lock.lock();

        try {

            System. out.println(count + " :---start name{}" + Thread.currentThread().getName() );
            System.out.println( lockObj.hashCode() );
            Thread.currentThread().sleep( 400 ); // 模拟执行一个耗时的任务
//            while ( count <=3 ){
                count ++;
//            }
            System.out.println(  );
//            try {
//                condSix.signalAll();
//            } catch (IllegalMonitorStateException e) {
//                e.printStackTrace();
//            }
            System. out.println(count + " : --- end name{} " + Thread.currentThread().getName() );
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
//            lock.unlock();
        }


@Override
    public  void  run() {
//        synchronized ( lockObj ){

//        lock.lock();

          print();

//
//       }


    }


    private synchronized void print(){
        try {

            System. out.println(count + " :---start name{}" + Thread.currentThread().getName() );
            System.out.println( lockObj.hashCode() );
            Thread.currentThread().sleep( 400 ); // 模拟执行一个耗时的任务
//            while ( count <=3 ){
            count ++;
//            }
            System.out.println(  );
//            try {


你可能感兴趣的:(Java,线程同步锁机制)