线程的同步与死锁 (同步 synchronization,死锁 deadlock)
        多线程的操作方法
    
        1.线程同步的产生与解决
        2.死锁的问题

    同步问题的的引出
        如果要想进行同步的操作,那么很明显就是多个线程需要访问同一资源
        
        范例:以卖票程序为例

package cn.mysterious.study3;

class MyThread implements Runnable{
private int ticket = 5;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
if (this.ticket > 0) {
System.out.println(Thread.currentThread().getName() + ",ticket = "+this.ticket --);
}
}
}
}
public class StudyThread { public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"票贩子A");
Thread t2 = new Thread(mt,"票贩子B");
Thread t3 = new Thread(mt,"票贩子C");
t1.start();
t2.start();
t3.start();
}
}

于是下面开始挖掘本程序所存在的问题
            
        范例:观察程序的问题

package cn.mysterious.study3;

class MyThread implements Runnable{
private int ticket = 5;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
if (this.ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ",ticket = "+this.ticket --);
}
}
}
}
public class StudyThread { public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"票贩子A");
Thread t2 = new Thread(mt,"票贩子B");
Thread t3 = new Thread(mt,"票贩子C");
t1.start();
t2.start();
t3.start();
}
}
// 结果出现了负数

bane这样的操作就属于线程的不同步的操作,所以发现多个线程操作时必须要考虑到资源同步的问题

    实现同步操作
        整个代码之中发现有一个逻辑上的流程错误了,以上的程序中,将判断是否有票,延迟,卖票分为了三个部分
        那么实际上每个线程如果要执行卖票的话,其他线程应该等待当前线程执行完毕后才可以进入
        
        如果要想在若干个代码上实现锁这个概念,那么就需要通过使用同步代码块或者同步方法来解决
        
        1.同步代码块
            使用 synchronized 关键字定义的代码块就称为同步代码块,但是在进行同步的时候需要设置有一个同步对象,那么往往可以使用 this 同步当前对象

package cn.mysterious.study3;

class MyThread implements Runnable{
private int ticket = 500;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 1000; i++) {
synchronized (this) {
if (this.ticket > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ",ticket = "+this.ticket --);
}
}
}
}
}
public class StudyThread { public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"票贩子A");
Thread t2 = new Thread(mt,"票贩子B");
Thread t3 = new Thread(mt,"票贩子C");
t1.start();
t2.start();
t3.start();
}
}

加入同步之后整个代码执行的速度已经变慢了,而已不像美誉同步的时候那样多个线程一起进入到方法之中
            异步的执行速度要快于同步的执行速度,但是异步的操作属于非线程安全的操作,而同步的操作属于线程的安全操作
            
        2.同步方法    
            但是对于同步操作,除了用于代码块定义之外,也可以在方法上定义同步操作

package cn.mysterious.study3;

class MyThread implements Runnable{
private int ticket = 500;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 1000; i++) {
sale();
}
}
public synchronized void sale(){ // 卖票
if (this.ticket > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ",ticket = "+this.ticket --);
}
}
}
public class StudyThread { public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"票贩子A");
Thread t2 = new Thread(mt,"票贩子B");
Thread t3 = new Thread(mt,"票贩子C");
t1.start();
t2.start();
t3.start();
}
}

在多个线程访问同一资源时一定要考虑到数据的同步问题,同步就使用 synchronized 关键字
    死锁分析(了解)
        很明显,死锁是一种不确定的状态,对于死锁的操作应该出现的越少越好,下面的代码只是一个死锁的演示,代码不做任何实际的意义

package cn.mysterious.study3;

class Kidnapper{  // 绑匪
public synchronized void say(Landlord dz){
System.out.println(" 绑匪说:给我3亿美金,放了你儿子!");
dz.get();
}
public synchronized void get(){
System.out.println("绑匪得到钱");
}
}
class Landlord{ // 地主
public synchronized void say(Kidnapper bf){
System.out.println(" 地主说:放了我儿子,再给钱!");
bf.get();
}
public synchronized void get(){
System.out.println("救回.....");
}
}
public class StudyThread implements Runnable{
private Kidnapper bf = new Kidnapper();
private Landlord dz = new Landlord();
public StudyThread (){
new Thread(this).start();
dz.say(bf);
}
public static void main(String[] args) throws Exception {
new StudyThread();
}
@Override
public void run() {
// TODO Auto-generated method stub
bf.say(dz);
}
}

面试题:请问多个线程访问同一资源时可能带来什么问题?以及会产生什么样的附加问题?
             多个线程访同一资源时必须考虑同步问题,可以使用 synchronized 定义同步代码块或者是同步方法
             程序中如果出现过多的同步那么就将产生死锁
            
    总结
        如果看见 synchronized 声明的方法,一定有爱记住这是一个同步方法,属于线程安全的操作

最新文章

  1. 贝塔阶段html及pdf模块测试
  2. JSONKit在项目中使用设置(ARC与方法更新)
  3. Java接口和抽象类的区别
  4. codeforces 723D: Lakes in Berland
  5. hdu1054 树形dp&amp;&amp;二分图
  6. overload, override和overwrite之间的区别
  7. topcoder 594 DIV2 foxandclassroom
  8. Using dbms_shared_pool.purge to remove a single task from the library cache
  9. ElasticSearch 的 聚合(Aggregations)
  10. ibatis配置多表关联(一对一、一对多、多对多)
  11. github 使用体会
  12. WCF分布式开发步步为赢(10):请求应答(Request-Reply)、单向操作(One-Way)、回调操作(Call Back).
  13. 第一百九十二天 how can I 坚持
  14. 【HTML】Beginner2:page title
  15. HDU 1134 卡特兰数 大数乘法除法
  16. Android手机怎样录制屏幕及转GIF
  17. 关于python的元类
  18. Python之禅及释义
  19. stylus入门教程,在webstorm中配置stylus
  20. 如何发布自己的node模块

热门文章

  1. NOIP模拟73
  2. Linux Bash命令杂记(tr col join paste expand)
  3. 阿里云 Serverless 再升级,从体验上拉开差距
  4. PHP伪协议与文件包含漏洞1
  5. Takin Talks&#183;上海 |开源后首场主题研讨会来了,一起解密Takin技术吧!
  6. Windows10使用技巧
  7. Noip模拟44 2021.8.19
  8. Linux该如何学习新手入门遇到问题又该如何解决
  9. STM32 学习笔记之中断应用概览--以f103为例
  10. HITS算法简介