码迷,mamicode.com
首页 > 编程语言 > 详细

Thread-线程的同步

时间:2020-07-01 16:10:12      阅读:68      评论:0      收藏:0      [点我收藏+]

标签:返回   size   效率   dem   vat   机制   bool   问题   方法   

线程的同步实现方式

方式一:同步代码块

synchronized(锁对象){
    //需要上锁的内容(同步代码块)
}

方式二:同步方法

public synchronized 返回类型 方法名(参数){
    //需要上锁的内容(同步代码块)
}

普通的同步方法,锁对象是this

静态的同步方法,锁对象是:当前类.class

要求

  1. 有多线程
  2. 多个线程使用的锁对象必须是同一个
  3. wait、notifiy、notifiyAll和当前同步代码的锁对象必须是同一个,否则报异常

扩展:

synchronized("abc"){} //可以实现线程同步,因为abc在字符串常量池中,但即使没有共享的对象也会需要排队等待

Object obj = new Object(); //可以定一个全局属性,实现有共享对象obj

synchronized(obj){}

案例:解决单例模式中懒汉式多线程问题

public class Singletion_Demo3 {
	public static void main(String[] args) {
		A a = new A();
		A b = new A();
		a.start();
		b.start();
	}
}
class A extends Thread{
	public void run() {
		for(int i=0;i<10;i++) {
			System.out.println(Single.getInstance());
		}
	}
}
class Single{
	private Single() {}
	private static Single s;
	public static Single getInstance() {
		if(s==null) //提高效率
			synchronized(Single.class) {
				if(s == null) { //线程安全
					try {
						Thread.sleep(100); //放大问题
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					s = new Single();
				}
			}
		return s;
	}
}

并发容器

CopyOnWriteArrayList

底层已经实现了线程同步

以下是不安全的线程

import java.util.ArrayList;
import java.util.List;

public class Thread_Demo1 {
	public static void main(String[] args) throws InterruptedException{
		List<Integer> listNum = new ArrayList<>();
		for(int i=0;i<100;i++) {
			new Thread(()->{
				for(int j=0;j<100;j++)
//					synchronized(listNum) {
						listNum.add(j);
//					}
			}).start();
		}
		Thread.sleep(5000);
		System.out.println(listNum.size());
	}
}

可以使用并发容器解决以上线程不安全问题

import java.util.concurrent.CopyOnWriteArrayList;

public class Thread_Demo2 {
	public static void main(String[] args) throws InterruptedException{
		CopyOnWriteArrayList<Integer> listNum = new CopyOnWriteArrayList<>();
		for(int i=0;i<100;i++) {
			new Thread(()->{
				for(int j=0;j<100;j++)
					listNum.add(j);
			}).start();
		}
		Thread.sleep(5000);
		System.out.println(listNum.size());
	}
}

线程死锁

产生

public class DeathLock {
	public static void main(String[] args) {
		new DeathMethod(true,"小红").start();
		new DeathMethod(false,"小明").start();
	}
}
class EatApple{
	public void eat() {
		System.out.println(Thread.currentThread().getName()+"吃苹果");
	}
}
class EatBanana{
	public void eat() {
		System.out.println(Thread.currentThread().getName()+"吃香蕉");
	}
}
class DeathMethod extends Thread{
	private static EatApple apple = new EatApple();
	private static EatBanana banana = new EatBanana(); ;
	boolean flag;
	public DeathMethod(boolean flag,String name) {
		super(name);
		this.flag = flag;
	}
	public void run() {
		if(flag) {
			synchronized(apple) {
				apple.eat();
				synchronized(banana) {
					banana.eat();
				}
			}
		}else {
			synchronized(banana) {
				banana.eat();
				synchronized(apple) {
					apple.eat();
				}
			}
		}
	}
}

就会出现以下情况,线程无法执行下去,一直在等待

小红吃苹果
小明吃香蕉

解决

更改run方法中的锁机制

不要在同一个代码块中,同时持有多个对象的锁

public void run() {
		if(flag) {
			synchronized(apple) {
				apple.eat();
			}
			synchronized(banana) { 
				banana.eat();
			}
		}else {
			synchronized(banana) {
				banana.eat();
			}
			synchronized(apple) {
				apple.eat();
			}
		}
	}

Thread-线程的同步

标签:返回   size   效率   dem   vat   机制   bool   问题   方法   

原文地址:https://www.cnblogs.com/xiaokw/p/MrXiaoK.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!