135 阅读3分钟

概述

 当多个线程共同访问一块内存时,便可能产生锁。考虑以下情况


线程A和线程B同时访问堆中的一个对象object,它们同时访问object.count变量,如果只是读取,不会存在如何问题,如果线程A和线程B都堆count进行改变。线程A发现如果count=0,该把count变成1,线程B发现如果count=0,就把A变成2。假设他们同时访问到count变量时,count=0,这是A先把count变成1,线程B接着把count变成2。线程A在进行访问时便出现了不一致的情况。

    为了解决不一致的情况,必须堆变量A进行加速处理,同一时间段,只允许一个线程对线程A进行访问,JAVA采用对对象进行加锁的方式进行处理,每一个对象的头部都有markword字段,使用markword的几个bit位表明对象是否具有访问一块代码片段的权限。

验证:

  验证环境:jdk1.8,VM参数:-XX:BiasedLockingStartupDelay=0

代码

import java.util.concurrent.TimeUnit;

import org.openjdk.jol.info.ClassLayout;

public class TestLock {
	static class LockObject {
		 int i=0;
	}
	static class MyThread implements Runnable {
		LockObject lock;
		public MyThread(LockObject lock) {
			this.lock = lock;
		}
		@Override
		public void run() {
			synchronized (lock) {
				System.out.println(ClassLayout.parseInstance(lock).toPrintable());
				try {
					Thread.sleep(TimeUnit.SECONDS.toMillis(3));
				} catch (Exception e) {
				}
			}
		}
	}
	public static void main(String[] args){
		LockObject lock = new LockObject();
		System.out.println(ClassLayout.parseInstance(lock).toPrintable());
		new Thread(new MyThread(lock)).start();
//		new Thread(new MyThread(lock)).start();
	}
	
}

运行结果:

TestLock$LockObject object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           43 c0 00 f8 (01000011 11000000 00000000 11111000) (-134168509)
     12     4    int LockObject.i                              0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

TestLock$LockObject object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           05 40 c3 1b (00000101 01000000 11000011 00011011) (465780741)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           43 c0 00 f8 (01000011 11000000 00000000 11111000) (-134168509)
     12     4    int LockObject.i                              0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

只有一个线程访问代码块时默认开启的是偏向锁:101

当开启两个线程时,锁变成了 010 (重量级锁),结果如下

TestLock$LockObject object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           43 c0 00 f8 (01000011 11000000 00000000 11111000) (-134168509)
     12     4    int LockObject.i                              0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

TestLock$LockObject object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           6a 40 72 02 (01101010 01000000 01110010 00000010) (41042026)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           43 c0 00 f8 (01000011 11000000 00000000 11111000) (-134168509)
     12     4    int LockObject.i                              0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

TestLock$LockObject object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           6a 40 72 02 (01101010 01000000 01110010 00000010) (41042026)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           43 c0 00 f8 (01000011 11000000 00000000 11111000) (-134168509)
     12     4    int LockObject.i                              0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total


锁的处理思路:

  java中:对象头中

  数据库:页锁