Java中线程同步和线程死锁问题

在这里我总结两方面的内容:线程同步与线程死锁,两者之间也存在一定关系,也正是因为线程同步才会处出现线程死锁的问题,现在首先来看线程同步的内容。

线程同步是这样一类问题:当一个有限的资源被多个线程共享的时候,为了保证对共享资源的互斥访问,我们一定要给他们排出一个先来后到。而要做到这一点,对象锁在这里起着非常重要的作用。每一个对象都有一把锁,而且只有一把锁,一个线程拿到之后别的对象便拿不到这个锁了,只能等那个线程执行完之后释放对象锁,别的线程才可以拿到锁执行后续操作,这样一来也就有了原子操作的概念,所谓原子操作就是那些不能被打断的操作,而加锁的过程就要用到 Synchronized,同步机制是通过对象锁来实现的,实现线程同步有以下几个方法和需要注意的地方:

同步方法有两种,可以同步方法,也可以同步语句块,同步方法就像平常的类修饰关键字一样,代码如下:

public synchronized void move(){

               //要同步的语句......

        }

也可以通过同步语句块的方式来实现,代码如下:

        synchronized(obj){

               //要同步的代码……

}

同步语句块里的obj是一个要同步的对象,那在同步的时候要注意的是同步必须是同步同一个对象,我们来看下面的例子:

public class Test {
		/**
		 * 
		 */
	public static void main(String[] args){
		MyThread t1 = new MyThread("t1");
		MyThread t2 = new MyThread("t2");
		MyThread t3 = new MyThread("t3");
		t1.start();
		t2.start();
		t3.start();
		
	}
	public static class MyThread extends Thread{
		private String name;
		public MyThread(String name){
			this.name = name;
		}
		public void run(){
			for(int i=0;i<100;i++){
				System.out.println("这是"+name+"的"+"第"+i+"个数");
			}
		}
	};
}

这段代码我希望的结果是想让三个线程对象分别数数,从1到100,但是要一个数完之后另一个再开始数,但是现在的输出结果却是这样子的:

我们可以看到,虽然每个线程对象内部是有序输出的,比如t1的顺序是从0到99,但是整体并不是t1完了之后再执行其他线程,我们想要的t1数数是一个原子操作,就是不能有其他的线程穿插进来,但是现在并不是这样子的效果,于是,我们改进为以下的代码:

public class Test {
		/**
		 * 
		 */
	
	public static void main(String[] args){
		Object obj = "string";
		MyThread t1 = new MyThread("t1",obj);
		MyThread t2 = new MyThread("t2",obj);
		MyThread t3 = new MyThread("t3",obj);
		
			t1.start();
			t2.start();
			t3.start();
		
	}
	public static class MyThread extends Thread{
		private String name;
		private Object obj;
		public MyThread(String name,Object obj){
			this.name = name;
			this.obj = obj;
		}
		public void run(){
			synchronized (obj) {
				for(int i=0;i<100;i++){
					System.out.println("这是"+name+"的"+"第"+i+"个数");
				}
			}
			
		}
	};
}

这样子之后的输出效果是这样子的:

这个我们可以很明显得看到达到了我们想要的效果,在这段代码里做的改动就是在mian里面声明了一个对象,然后作为共享的对象传入线程里,三个线程在执行的时候由于拿到的是同一个对象,这个对象就好比是共享的资料一样,这个对象只有一把锁,在系统调度t1线程进入run之后拿到了对象的锁,之后就必须让for执行完,之后释放锁,别的线程才可以拿到,这样就让每个线程变成了一个原子操作,在写的时候很可能会犯这样的错误,请看代码:

public class Test {
		/**
		 * 
		 */
	
	public static void main(String[] args){
		Object obj = "string";
		MyThread t1 = new MyThread("t1",obj);
		MyThread t2 = new MyThread("t2",obj);
		MyThread t3 = new MyThread("t3",obj);
		synchronized (obj) {
			t1.start();
		}
		synchronized (obj) {
			t2.start();
		}
		synchronized (obj) {
			t3.start();
		}
			
			
		
	}
	public static class MyThread extends Thread{
		private String name;
		private Object obj;
		public MyThread(String name,Object obj){
			this.name = name;
			this.obj = obj;
		}
		public void run(){
			
				for(int i=0;i<100;i++){
					System.out.println("这是"+name+"的"+"第"+i+"个数");
				}
			}
			
		
	};
}

这样子的运行效果和第一种类似,先写到这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值