synchronized的简单应用

1.synchronized关键字简介

synchronized简单来说就是一把隐形锁,可以系统调度,也可以自主调度。

线程控制的注意点:

/*
 * synchronized在jdk1.6前是重量级锁,即映射到OS的线程控制,资源开销大,后改进成JVM上的线程控制,成了轻量级锁
 * --------
 * 注意:Thread的线程是由你启动的那个implements Runnable的类控制的,如果你Thread传入的对象不是同一个
 * 那么你不同的线程访问到的数据就不一样了,即资源不共享,除非是静态资源
 * synchronized如果锁的是类(静态)级别的,那么就是所有对象共用。不然范围就只是在该对象。
 * --------
 * 可以为代码区加锁,方法加锁,数据加锁。
 * --------
 * synchronized是通过监视器达到线程管理的,这种lock通过Monitor形成阻塞队列自动调度管理
 * 所以在调用wait和notify时要注意对调用对象进行锁定,不然无法调度阻塞队列管理
 * */

2.synchronized调用实例

示范不同加锁方式:synchronized可以对代码区加锁,方法加锁,数据加锁,而wait()和notify()也是Object类的方法,所以适用性很广,但是要进行对象锁定比较麻烦。

自动阻塞唤醒调度示例:(当被锁定的代码发生竞争时,自动阻塞,直到运行线程结束释放锁,自动唤醒阻塞队列中的线程。注意,同时不被锁定的资源可以共享)

public class SExam implements Runnable {
	private Byte[] lock = new Byte[0];
	private int count = 0;
	private static int scount = 0;

	@Override
	public void run() {
		for (int i = 0; i < 2; i++) {
			// lock the codeArea, stop for 1s
			synchronized (this) {
				try {
					read_code();
					Thread.sleep(1000);
				} catch (Exception e) {
					System.out.println(e);
				}
			}
			// entity method lock, stop for 1s
			try {
				write();
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			// class method lock, stop for 1s
			try {
				sWrite();
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			// lock the code for lock the data, stop for 1s
			synchronized (lock) {
				try {
					read_data();
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

			}
		}

	}

	public void read_code() {
		System.out.println(Thread.currentThread().getName() + " to the codeAreaLock -- count read: " + count);
	}

	public void read_data() {
		System.out.println(Thread.currentThread().getName() + " to the dataLock -- count read: " + count);
	}

	public synchronized void write() {
		count++;
		System.out.println(Thread.currentThread().getName() + " to the entityLock -- count read: " + count);
	}

	public static synchronized void sWrite() {
		scount++;
		System.out.println(Thread.currentThread().getName() + " to the classLock -- scount read: " + scount);
	}

}

wait即释放锁,进入休眠,等待唤醒。notify即进行队列线程唤醒,占有锁。

notify是根据monitor管理的队列随机唤醒,所以要区分好唤醒哪个队列的线程。(还有notifyAll()在主线程上也较为常用)

手动调度阻塞唤醒示例:(模拟对资源的同步提供与获取)

public class SWaitAndNotify implements Runnable {
	private Byte[] lock = new Byte[0];
	private int source = 0;
	private Integer full = new Integer(0), empty = new Integer(0);

	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			try {
				offer();
				Thread.sleep(1000);
				require();
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void offer() throws InterruptedException {
		synchronized (lock) {
			synchronized (full) {
				if (source >= 10)
					full.wait();
			}
			source++;
			System.out.println(Thread.currentThread().getName() + ":+1=" + source);
			synchronized (empty) {
				empty.notify();
			}
		}
	}

	public void require() throws InterruptedException {
		synchronized (lock) {
			synchronized (empty) {
				if (source == 0)
					empty.wait();
			}
			source--;
			System.out.println(Thread.currentThread().getName() + ":-1=" + source);
			synchronized (full) {
				full.notify();
			}
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值