线程不安全
数据在多个进程访问时发生数据不准确的情况
同步锁
同步方法
同步块
并发容器
CopyOnWriteArrayList<Integer> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
死锁
过多的同步块会导致线程之间相互请求对方已经锁定的资源,从而导致死锁
package Thread1;
public class DeadLock {
public static void main(String[] args) {
new Thread(new MakeUp(1,"JYG1")).start();
new Thread(new MakeUp(2,"JYG2")).start();
}
}
class Lipstick{
}
class Mirro{
}
class MakeUp implements Runnable{
private static Lipstick lipstick = new Lipstick();
private static Mirro mirro = new Mirro();
String name;
int choice;
public MakeUp(int choice,String name) {
this.choice = choice;
this.name = name;
}
@Override
public void run() {
if (choice == 1){
synchronized (lipstick){
System.out.println(name+"拿到了口红");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirro){
System.out.println(name+"照着了镜子");
}
}
}else {
synchronized (mirro){
System.out.println(name+"照着了镜子");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lipstick){
System.out.println(name+"拿到了口红");
}
}
}
}
}
代码逻辑:
前提,Lipstick和Mirro在内存中只有一份
时刻0
线程JYG1锁定了Lipstick,线程JYG2锁定了Mirro
时刻1
线程JYG1在锁定Lipstick的同时,又想请求Mirro
线程JYG2在锁定Mirro的同时,又想请求Lipstick.
时刻N
两个线程一直等待对方释放自己想要的资源
解决:
package Thread1;
public class DeadLock {
public static void main(String[] args) {
new Thread(new MakeUp(1,"JYG1")).start();
new Thread(new MakeUp(2,"JYG2")).start();
}
}
class Lipstick{
}
class Mirro{
}
class MakeUp implements Runnable{
private static Lipstick lipstick = new Lipstick();
private static Mirro mirro = new Mirro();
String name;
int choice;
public MakeUp(int choice,String name) {
this.choice = choice;
this.name = name;
}
@Override
public void run() {
if (choice == 1){
synchronized (lipstick){
System.out.println(name+"拿到了口红");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirro){
System.out.println(name+"照着了镜子");
}
}else {
synchronized (mirro){
System.out.println(name+"照着了镜子");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lipstick){
System.out.println(name+"拿到了口红");
}
}
}
}
避免套锁,不用再一个同步块中同时持有多个对象的锁
生产者消费者问题
管程法
package Thread1;
public class CoTest {
public static void main(String[] args) {
Factory factory = new Factory();
Productor productor = new Productor(factory);
Consumor consumor = new Consumor(factory);
new Thread(productor).start();
new Thread(consumor).start();
}
}
//生产者
class Productor implements Runnable{
Factory factory ;
public Productor(Factory factory) {
this.factory = factory;
}
//生产
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println("生产第"+i+"个工作");
factory.push(new Jod(i));
}
}
}
//消费者
class Consumor implements Runnable{
Factory factory;
public Consumor(Factory factory) {
this.factory = factory;
}
//消费
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println("消费了第"+i+"个工作");
factory.pop();
}
}
}
//缓存区
class Factory{
Jod[] jods = new Jod[10];
int count = 0;
//生产
public synchronized void push(Jod jod){
if (count == jods.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
jods[count] = jod;
count++;
this.notifyAll();
}
//消费
public synchronized Jod pop(){
if (count ==0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
this.notifyAll();
return jods[count];
}
}
//产品
class Jod{
private int id;
public Jod(int id) {
this.id = id;
}
}
代码逻辑
角色:生产者,消费者,工厂(缓存区),资源(产品)
缓存区大小为10
设定生产者能生产100个资源
设定消费者能消费100个资源
-----------时刻0------------->
等待条件:生产者往工厂中有放满了资源或者消费者消费完了工厂中的资源
生产者生产资源
消费者消费资源
-----------时刻1------------->
唤醒条件:工厂中有足够的空间可以生产或者有资源可以消费
生产者生产资源
消费者消费资源
-----------时刻2------------->
100个资源全部生产完成,100个资源全部消费完成
信号灯法
package Thread1;
/**
* 信号灯法
*/
public class CoTest02 {
public static void main(String[] args) {
TvShow tvShow = new TvShow();
new Thread(new Player(tvShow)).start();
new Thread(new Watcher(tvShow)).start();
}
}
class Player implements Runnable{
TvShow tvShow ;
public Player(TvShow tvShow) {
this.tvShow = tvShow;
}
@Override
public void run() {
for (int i=0;i<10;i++){
if (i%2 ==0 ){
this.tvShow.paly("编程大战");
}else {
this.tvShow.paly("广告时间");
}
}
}
}
class Watcher implements Runnable{
TvShow tvShow ;
public Watcher(TvShow tvShow) {
this.tvShow = tvShow;
}
@Override
public void run() {
for (int i=0;i<10;i++){
this.tvShow.watch();
}
}
}
class TvShow{
String showName;
boolean flag = true;//true为表演节目观众等待,false观众观看演员表演
public synchronized void paly(String showName){
if (!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.showName = showName;
System.out.println("表演了"+this.showName);
this.notifyAll();
this.flag = !this.flag;
}
public synchronized void watch(){
if (flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("观看了"+this.showName);
this.notifyAll();
this.flag = !this.flag;
}
}
根据标志位来控制线程是等待还是唤醒