java中的每一个对象都可以作为synchronized的锁进行代码同步,常见的形式
synchronized是通过指定某个对象进行加锁,那么synchronized的锁信息肯定是和对象有关。Java的对象头里的Mark Word字段,默认是存储对象的HashCode。32位虚拟机中Mark Word的存储结构
锁状态 | Mark Word中的存储内容 | 标志位 |
---|---|---|
无锁状态 | Hash code,偏向锁0 | 01 |
偏向锁 | 线程ID,偏向锁1 | 01 |
轻量级锁 | 指向栈中锁记录的指针 | 00 |
重量级锁 | 指向互斥量的指针 | 10 |
偏向锁 ==> 轻量级锁 ==> 重量级锁
锁只能升级、不能退化
锁 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
偏向锁 | 加锁和解锁不需要额外的消耗,和执行非同步方法比仅存在纳秒级的差距 | 如果线程间存在锁竞争,会带来额外的锁撤销的消耗 | 适用于只有一个线程访问同步块场景 |
轻量级锁 | 竞争的线程不会阻塞,提高了程序的响应速度 | 如果始终得不到锁竞争的线程使用自旋会消耗CPU | 追求响应时间,锁占用时间很短 |
重量级锁 | 线程竞争不使用自旋,不会消耗CPU | 线程阻塞,响应时间缓慢 | 追求吞吐量,锁占用时间较长 |
如果你看到别人在非并发环境下使用StringBuffer就说,你这里应该用StringBuilder啊,用StringBuffer明显影响性能。这句话前面半句是没问题的,但是说明显影响性能这个就有点显得不那么专业了。如果你看明白的了synchronized的锁升级就应该知道,在单线程环境下永远是偏向锁,不会升级。因此性能开销可以忽略不计。
- As of release JDK 5, this class has been supplemented with an equivalent
- class designed for use by a single thread, link StringBuilder. The
- StringBuilder class should generally be used in preference to
- this one, as it supports all of the same operations but it is faster, as
- t performs no synchronization.
- public class TTT {
- public static void main(String[] args) throws ParseException,
- InterruptedException {
- new MyThread("A").start();
- synchronized(new String("B")) {
- new MyThread("B").start();
- }
- new MyThread("A").start();
- }
- public static void synchronizeMethod(String str) throws InterruptedException {
- synchronized(str) {
- TimeUnit.SECONDS.sleep(2);
- System.out.println(str);
- }
- }
- static class MyThread extends Thread {
- String str;
- public MyThread(String str) {
- this.str = str;
- }@Override public void run() {
- try {
- synchronizeMethod(str);
- } catch(InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
你知道上面代码的执行情况吗。如果不明白那说明synchronized使用和String的内存分配情况还有欠缺。
来源: http://www.cnblogs.com/lizo/p/7570740.html