java多线程 学习总结(2)

4.线程的同步
4.1 为什么会存在线程安全问题?
多个线程操作共享数据的时候,为执行完的情况下,另外的线程参与进来,导致共享数据存在安全问题
4.2 如何解决线程的安全问题?
在一个线程操作共享数据的时候,必须让这个线程操作完毕之后,其他线程才有机会参与操作
4.3 java中的线程同步机制
方式一、同步代码块
synchronized(同步监视器){
//需要同步的代码块
}
1. 共享数据
2. 同步监视器,由一个类来充当(任何一个类都有可以) 哪个线程获取此监视器,就执行同步代码块、
要求:在需要所有线程都操作同一数据的时候,所有的线程必须公用同一把锁。
一般在实现Runnable接口的的方式中使用this充当同步监视器
而在继承Thread的方式中,共享数据和同步监视器都应该标识为 static 才能达到同步的效果
方式二、同步方法
show();
public synchronized void show(){
}
将操作共享数据的方法声明为synchronized,当一个线程在执行此方法的时,其他线程只有等待该线程执行完毕之后才可以操作同步方法
和同步代码块存在一样的问题,两种线程同步的方式,在操作过程中都应该公用一把锁,
而在继承Thread的方式中,所有的线程都会同时的拥有自己的一把锁(当前对象),这种方式在同步代码块中只需要将当前对象声明为 static 即可解决。而在同步方法中,也可以这样解决

4.4 单利模式的线程安全问题
    单利模式(懒汉式)同样的在并发的情况下,有可能发生线程安全问题。使用synchronized(this){}同步代码块同样可以解决。

4.5 线程同步的好处
    可以使得程序数据更加的安全。
        注:在使用实现Runnable接口创建线程的时候,可以使用this(当前对象)来充当锁(同步监视器)。
        但在使用继承Thread类创建线程的时候,必须保证每个独立线程都公用一把锁的,this慎重使用。
    弊端
    在使用线程同步的同时,虽然增加了数据的安全性,但是因为在同一时间只能执行一个线程,
    但效率变低了
    有可能出现死锁

4.6 锁
    释放锁的操作
        当前线程同步代码块 同步方法执行结束之后释放
        当前线程执行期间出现了未处理的Error 和 Exception
        执行了当前对象的wait()方法
        sleep()方法和wait()方法的区别
            sleep()方法在线程执行中不会释放资源
            wait()方法在线程执行的时候会释放资源
4.7 死锁
        不同的线程在执行过程中分别占用对方需要的资源不放弃,都在等待对方放弃自己需要的源就形成了死锁

    解决方法
        专门的算法 规则
        尽量减少同步资源的定义

5.线程的通信
设计到三个方法
wait(): 令线程挂起 并放弃CPU资源,同步资源
notifyAll(): 唤醒正在排队等待同步资源的所有线程结束等待
notify(): 唤醒正在排队等待同资源的线程优先级最高者结束等待
使用方式 都必须在同步代码块中使用

6.生产者和消费者
class Clerk {// 商店
int product = 10;// 商品

public synchronized void addProduct() {
    if (product >= 20) {
        try {
            wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } else {
        product++;
        System.out.println(Thread.currentThread().getName() + ":生产了第" + product + "产品");
        notifyAll();
    }
}

public synchronized void customer() {
    if (product <= 0) {
        try {
            wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } else {
        System.out.println(Thread.currentThread().getName() + ":消费了第" + product + "产品");
        product--;
        notifyAll();
    }
}

}

class Customer1 implements Runnable {// 消费者
Clerk clerk;

public Customer1(Clerk clerk) {
    this.clerk = clerk;
}

@Override
public void run() {
    while (true) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        clerk.customer();
    }
}

}

class Producer implements Runnable {// 生产者
Clerk clerk;

public Producer(Clerk clerk) {
    this.clerk = clerk;
}

@Override
public void run() {
    while (true) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        clerk.addProduct();
    }
}

}

线程同步的练习
有一个银行账户,两个储户向同一个账号存钱,每次存1000,每次存完打印账户余额
package com.feng.thread;

        class Bank {
            private int money = 0;
            public int getMoney() {
                return money;
            }
            public void setMoney(int money) {
                this.money = money;
            }
        }
        class Person implements Runnable {
            private Bank bank = new Bank();
            int money = 0;  
            @Override
            public void run() {
                while (true) {
                    synchronized (this) {
                        if (money < 3000) {
                            bank.setMoney(money+=1000);
                            System.out.println(Thread.currentThread().getName() + "存入了:====" + "1000" + " 当前余额:====" + bank.getMoney());
                        } else {
                            return;
                        }
                    }
                }
            }

        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值