Java基础针对自己薄弱环节总结09(线程中)

一、同步代码块、同步方法

1、同步代码块     

  synchronized(锁对象){
          需要被锁的代码 //线程只有拿到了锁对象,才能执行这里的代码!!!换言之,这里的代码如果执行了,说 明该 线程拿到了锁对象,其他线程不能拿到该锁对象
     }

     注意
          多个线程必须使用同一个锁对象,要不然锁无效

2、同步方法

     public synchronized void show(){}               //普通方法的锁是this
     public static synchronized void show(){}    //静态方法的锁是当前类的字节码文件对象 类名.class
3、注意问题

     多个线程必须使用同一个锁对象,要不然锁无效
     同步代码块锁可以是任意对象
     同步方法的锁是this
     静态方法的锁是当前类的字节码文件对象 类名.class 

二、死锁
死锁原因:线程1占有着A锁,线程2拿着B锁,当线程1要用B锁,线程2要用A锁时,发生死锁。

代码体现

package cn.itcast.thread;
/**
 * 线程1类
 * @author LBK
 *
 */
public class Thread01 extends Thread {

	@Override
	public void run() {
		synchronized (Lock.LOCK_A) {
			System.out.println("我是线程1,我拿着锁A,现在需要拿锁B");
			synchronized (Lock.LOCK_B) {
				System.out.println("我是线程1,成功拿到锁B");
			}
		}
	}
}

package cn.itcast.thread;
/**
 * 线程2类
 * @author LBK
 *
 */
public class Thread02 extends Thread{
	@Override
	public void run() {
		synchronized (Lock.LOCK_B) {
			System.out.println("我是线程2,我拿着锁B,现在需要拿锁A");
			synchronized (Lock.LOCK_A) {
				System.out.println("我是线程2,成功拿到锁A");
			}
		}
	}
}

package cn.itcast.thread;
/**
 * 锁类
 * @author LBK
 *
 */
public class Lock {
	public static final Object LOCK_A=new Object();
	public static final Object LOCK_B=new Object();
}

package cn.itcast.thread;
/**
 * 测试类
 * @author LBK
 *
 */
public class ThreadTest {
	public static void main(String[] args) {
		Thread01 t1=new Thread01();
		Thread02 t2=new Thread02();
		t1.start();
		t2.start();
	}
}

结果:



右边红色证明程序一直没有停止,发生了死锁。(解决方案在这里先不说了,以后再和大家分享)


三、多个线程操作同一数据的问题(线程间的通讯问题)


其实就是多个线程同时操作同一个对象
      卖票案例就是线程间通讯问题

下面是问题代码(因为没有对操作共享数据的代码加入同步代码块)

class Student {

       public String name;

       public int age;

 

       @Override

       public String toString() {

              return "Student [name=" + name + ", age=" + age + "]";
       }
}
class SetThread  extends Thread{

       private Student stu;

       public SetThread(Student stu){

              this.stu = stu;

       }
       @Override
       public void run() {
              int i=0;
              while(true){

                     if(i%2 ==0){//执行%2操作,是为了写入不同的数据,测试在写入过程中,是否影响另一个线程的读取操作

                            stu.name = "张三";

                            stu.age = 13;

                     }else{
                            stu.name = "李四";
                            stu.age = 14;
                     }
                     i++;
              }
       }

}
class GetThread extends Thread {

       private Student stu;

       public GetThread(Student stu){
              this.stu = stu;
       }

       @Override

       public void run() {

              while(true){

                     System.out.println(stu);
              }
       }

}
public class Test {

       public static void main(String[] args) {

              //创建共享数据

              Student stu = new Student();

              //创建两个线程,并且让这两个线程同时操作这个共享数据

              GetThread get = new GetThread(stu);

              SetThread set = new SetThread(stu);

              get.start();

              set.start();

       }
}

结果:出现错误数据



错误原因:在SetThread刚做完if赋值时,GetThread抢到,开始执行,此时输出正确,但是当SetThread执行到else中的对年龄赋值时,GetThread抢到开始执行,输出的是张三 ,14。


解决方案1:加锁(把上面两个线程中的共享数据加锁,锁就是stu对象)

class SetThread extends Thread {
	private Student stu;
	public SetThread(Student stu) {
		this.stu = stu;
	}
	@Override
	public void run() {
		int i = 0;
		while (true) {
			synchronized (stu) {
				if (i % 2 == 0) {// 执行%2操作,是为了写入不同的数据,测试在写入过程中,是否影响另一个线程的读取操作
					stu.name = "张三";
					stu.age = 13;
				} else {
					stu.name = "李四";
					stu.age = 14;
				}
				i++;
			}
		}
	}
}
class GetThread extends Thread {
	private Student stu;
	public GetThread(Student stu) {
		this.stu = stu;
	}
	@Override
	public void run() {
		while (true) {
			synchronized (stu) {
				System.out.println(stu);
			}
		}
	}
}

解决方案2:(等待唤醒机制)请看下篇分解


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值