高并发编程:7、synchronized

一、概述

  • synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性。
  • 多线程访问synchronized方法或代码块时,变成了单线程串行的方式。

二、基本认识

package com.cfl.thread;

public class Thread7 {
    private final static Object MONITOR = new Object();
    public static void main(String[] args) throws Exception {
	Runnable runnable = new Runnable() {
	    public void run() {
		try {
		    synchronized (MONITOR) {
	                System.out.println(Thread.currentThread().getName());
			Thread.sleep(100*1000);
		    }
		} catch (InterruptedException e) {
		    e.printStackTrace();
		}
	    }
	};
	Thread thread1 =  new Thread(runnable);
	Thread thread2 =  new Thread(runnable);
	Thread thread3 =  new Thread(runnable);
	thread1.start();
	thread2.start();
	thread3.start();
    }
}
# 控制台打印
Thread-0


# jconsole查看线程
名称: Thread-0
状态: TIMED_WAITING
总阻止数: 0, 总等待数: 1
堆栈跟踪: 
java.lang.Thread.sleep(Native Method)
com.cfl.thread.Thread7$1.run(Thread7.java:14)
   - 已锁定 java.lang.Object@70866080
java.lang.Thread.run(Thread.java:748)



名称: Thread-1
状态: java.lang.Object@70866080上的BLOCKED, 拥有者: Thread-0
总阻止数: 1, 总等待数: 0
堆栈跟踪: 
com.cfl.thread.Thread7$1.run(Thread7.java:13)
java.lang.Thread.run(Thread.java:748)



名称: Thread-2
状态: java.lang.Object@70866080上的BLOCKED, 拥有者: Thread-0
总阻止数: 1, 总等待数: 0
堆栈跟踪: 
com.cfl.thread.Thread7$1.run(Thread7.java:13)
java.lang.Thread.run(Thread.java:748)
  • 可以看到Thread-0在执行,状态:TIMED_WAITING。
  • Thread-1和Thread-2已锁,状态:BLOCKED

二、同步代码块和方法

static class SynchronizedLock {
    private final Object LOCK = new Object();
    public void m1() {
	System.out.println(Thread.currentThread().getName() + " start ");
	synchronized (LOCK) {
	    try {
        	System.out.println(Thread.currentThread().getName() + " synchronized");
	        Thread.sleep(10*1000);
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }
	}
    }
    public synchronized void m2() {
	try {
	    System.out.println(Thread.currentThread().getName() + " synchronized");
	    Thread.sleep(10*1000);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
    }
    public synchronized void m3() {
	try {
	    System.out.println(Thread.currentThread().getName() + " synchronized");
	    Thread.sleep(10*1000);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
    }
}

1、同步代码块

public static void main(String[] args) throws Exception {
    final SynchronizedLock lock = new SynchronizedLock();
    Thread thread1 =  new Thread(new Runnable() {
	public void run() {
	    lock.m1();
	}
    });
    Thread thread2 =  new Thread(new Runnable() {
	public void run() {
	    lock.m1();
	}
    });
    Thread thread3 =  new Thread(new Runnable() {
	public void run() {
	    lock.m1();
	}
    });
    thread1.start();
    thread2.start();
    thread3.start();
}
Thread-2 start 
Thread-0 start 
Thread-1 start 
Thread-2 synchronized
  • m1方法是并行执行的,但是m1方法LOCK锁里面的代码块时串行执行的。

2、同步方法

public static void main(String[] args) throws Exception {
    final SynchronizedLock lock = new SynchronizedLock();
    Thread thread1 =  new Thread(new Runnable() {
	public void run() {
	    lock.m2();
	}
    });
    Thread thread2 =  new Thread(new Runnable() {
	public void run() {
	    lock.m2();
	}
    });
    Thread thread3 =  new Thread(new Runnable() {
	public void run() {
	    lock.m3();
	}
    });
    thread1.start();
    thread2.start();
    thread3.start();
}
Thread-0 synchronized
  • 当synchronized同步方法时,该方法串行执行。
  • synchronized同步方法时,实际上是this锁。 

三、this锁

package com.cfl.thread;

public class Thread7 {
    public static void main(String[] args) throws Exception {
	final SynchronizedLock lock = new SynchronizedLock();
	Thread thread1 =  new Thread(new Runnable() {
	    public void run() {
		lock.m1();
	    }
	});
	Thread thread2 =  new Thread(new Runnable() {
	    public void run() {
		lock.m1();
	    }
	});
	Thread thread3 =  new Thread(new Runnable() {
	    public void run() {
		lock.m2();
	    }
	});
        Thread thread4 =  new Thread(new Runnable() {
	    public void run() {
		lock.m3();
	    }
	});
	thread1.start();
	thread2.start();
	thread3.start();
        thread4.start();
    }
	
    static class SynchronizedLock {
	public void m1() {
            System.out.println(Thread.currentThread().getName() + " start");
	    synchronized (this) {
		try {
		    System.out.println(Thread.currentThread().getName() + " synchronized");
		    Thread.sleep(10*1000);
		} catch (InterruptedException e) {
		    e.printStackTrace();
		}
	    }
	}
	public synchronized void m2() {
	    try {
	        System.out.println(Thread.currentThread().getName() + " synchronized");
	        Thread.sleep(10*1000);
	    } catch (InterruptedException e) {
	        e.printStackTrace();
	    }
        }
        public synchronized void m3() {
	    try {
	        System.out.println(Thread.currentThread().getName() + " synchronized");
	        Thread.sleep(10*1000);
	    } catch (InterruptedException e) {
	        e.printStackTrace();
	    }
        }
    }
}
Thread-0 start
Thread-2 synchronized
Thread-1 start
  • 当synchronized用this同步代码块的时候,代码块里面的内容和方法也是串行执行。
  • 代码块外面的代码并行执行

4、this锁和对象锁并存

package com.cfl.thread;

public class Thread7 {
    public static void main(String[] args) throws Exception {
	final SynchronizedLock lock = new SynchronizedLock();
	Thread thread1 =  new Thread(new Runnable() {
	    public void run() {
		lock.m1();
	    }
	});
	Thread thread2 =  new Thread(new Runnable() {
	    public void run() {
		lock.m2();
	    }
	});
	Thread thread3 =  new Thread(new Runnable() {
	    public void run() {
		lock.m3();
	    }
	});
	thread1.start();
	thread2.start();
	thread3.start();
    }
	
    static class SynchronizedLock {
        private final Object LOCK = new Object();
	public void m1() {
            System.out.println(Thread.currentThread().getName() + " start");
	    synchronized (LOCK) {
		try {
		    System.out.println(Thread.currentThread().getName() + " synchronized");
		    Thread.sleep(10*1000);
		} catch (InterruptedException e) {
		    e.printStackTrace();
		}
	    }
	}
	public synchronized void m2() {
	    try {
	        System.out.println(Thread.currentThread().getName() + " synchronized");
	        Thread.sleep(10*1000);
	    } catch (InterruptedException e) {
	        e.printStackTrace();
	    }
        }
        public synchronized void m3() {
	    try {
	        System.out.println(Thread.currentThread().getName() + " synchronized");
	        Thread.sleep(10*1000);
	    } catch (InterruptedException e) {
	        e.printStackTrace();
	    }
        }
    }
}
Thread-0 start
Thread-0 synchronized
Thread-1 synchronized
  • this锁和对象锁互相独立,并行执行。

四、Class锁

package com.cfl.thread;

/**
 * Synchronized class锁
 * @author chenfenli
 *
 */
public class Thread8 {
    public static void main(String[] args) throws Exception {
	Thread thread1 =  new Thread(new Runnable() {
	    public void run() {
		ClassLock.m1();
	    }
	},"T1");
	Thread thread2 =  new Thread(new Runnable() {
	    public void run() {
                ClassLock.m2();
	    }
	},"T2");
	Thread thread3 =  new Thread(new Runnable() {
	    public void run() {
		ClassLock.m3();
	    }
	},"T3");
	Thread thread4 =  new Thread(new Runnable() {
	    public void run() {
		ClassLock.m4();
	    }
	},"T4");
	thread1.start();
	thread2.start();
	thread3.start();
	thread4.start();
    }
    static class ClassLock {
	static {
	    synchronized (ClassLock.class) {
		System.out.println(Thread.currentThread().getName() + " 静态块 " + System.currentTimeMillis() +  " synchronized");
		try {
		    Thread.sleep(10*1000);
		} catch (InterruptedException e) {
		    e.printStackTrace();
		}
	    }
	}
	public synchronized static void m1() {
	    System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis() +  " synchronized");
	    try {
		Thread.sleep(10*1000);
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }
	}
	public synchronized static void m2() {
	    System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis() +  " synchronized");
	    try {
		Thread.sleep(10*1000);
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }
	}
	public synchronized static void m3() {
	    System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis() +  " synchronized");
	    try {
		Thread.sleep(10*1000);
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }
	}
	public static void m4() {
	    System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis() +  " synchronized");
	}
    }
}
T1 静态块 1563370479790 synchronized
T4 1563370489794 synchronized
T1 1563370489794 synchronized
T2 1563370499797 synchronized
T3 1563370509802 synchronized
  • 可以看到静态块里面的锁在初始化对象的时候最先开始执行。
  • 静态块里面的锁执行完成之后,锁被T1抢到,T1和不加锁的T4同时执行。
  • T1执行完之后锁被T2抢到。
  • T2执行完之后被T3抢到锁,执行完成。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值