Java线程锁

学习多线程大家都对它的锁感到郁闷,一般它的锁对象可以有Object,当前类对象this,以及修饰static方法时的类class文件。

比如对于同步代码块:

while (true) {
			synchronized (this) {
				if (ticket > 0) {
					try {
						Thread.currentThread().sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "还有"
							+ (ticket--) + "张票");
				} else
					break;
			}

对于函数中的同步锁:

	public synchronized void show(){
		while (true) {
				if (ticket > 0) {
					try {
						Thread.currentThread().sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "还有"
							+ (ticket--) + "张票");
				} 
		}
	}

以及static函数中的同步锁:

public synchronized static void show2(){
		//省略代码
	}

他们3者之间的锁对象不同,对于代码块来说,它的锁是任意的Object对象,如果我们使用了代码块和函数同步,那么我们的锁对象要换位this,这样才能保证线程的安全性,而如果我们使用static函数和代码块同步锁,那么锁对象要使用static函数所在的类的class代码块,如ThreadDemo1.class。

对于两个或两个以上的线程访问同一个资源时,要注意线程的安全问题,如:Input线程向Res类中写数据,Output读数据。

资源对象:

package lh.zjzk;

/**
 * 此资源类似与,工厂流水线上的产品,一进,一出
 * @author Administrator
 *
 */
public class Res {
	public String name;
	public String sex;
	public boolean flag = false;//是否对调用该对象的线程进行锁定以及唤醒
}

加工线程:

package lh.zjzk;

public class Input implements Runnable {
	private Res res;
	public Input(Res res) {
		this.res = res;
	}
	int x = 0 ;
	@Override
	public void run() {
		while(true){
			synchronized(res){//为了保证Input和Output这两个线程使用的是同一个锁,故将res对象传递给同步代码块
					try {
						if(res.flag)//如果Res已经被赋值,那么将Input线程锁定,等待Output唤醒
							res.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					if(x % 2 ==0){
						res.name = "张三";
						res.sex = "男";
					}else{
						res.name = "xiaoxiao";
						res.sex = "女";
					}
					x = (x+1) % 2;
					res.flag = true;//赋值过后,将唤醒标志改为true
					res.notify();//唤醒Output线程输出
			}
		}
	}

}

搬运线程:

package lh.zjzk;

public class Output implements Runnable {
	private Res res;
	public Output(Res res){
		this.res = res;
	}
	@Override
	public void run() {
		while(true){
			synchronized(res){
				try {
					if(!res.flag)//如果真,证明资源已经被赋值了,该线程应把它拿走,否则等待
						res.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(res.name + "--->"+res.sex);
				res.flag = false;//将唤醒标志改为false
				res.notify();//唤醒Input对象进行赋值
			}
		}
	}

}

主程序调用加工和搬运线程进行操作:

package lh.zjzk;

public class ThreadMain {

	public static void main(String[] args) {
		Res res = new Res();
		Input in = new Input(res);
		Output out = new Output(res);
		new Thread(in).start();
		new Thread(out).start();
	}

}

输出结果:

《Java线程锁》



    原文作者:java锁
    原文地址: https://blog.csdn.net/AS_MSDN/article/details/30967859
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞