Java多线程理解(线程安全)

我们在使用Java多线程时,一定需要考虑到共享,线程安全的相关内容。以下通过几个例子帮助大家来理解多线程时如何运行的,后续通过一篇文章详述解决办法:synchronized。

场景1:

第一次运行结果:

[当前线程]----------one=====实例变量的值----x=1

[当前线程]----------two=====实例变量的值----x=2

[当前线程]----------two=====实例变量的值----x=3

[当前线程]----------two=====实例变量的值----x=4

[当前线程]----------two=====实例变量的值----x=5

[当前线程]----------two=====实例变量的值----x=6

[当前线程]----------one=====实例变量的值----x=7

[当前线程]----------one=====实例变量的值----x=8

[当前线程]----------one=====实例变量的值----x=9

[当前线程]----------one=====实例变量的值----x=10

分析总结:我们在这里看到运行结果从1-10,线程th1和线程th2各自增加,此时两个线程公用一个对象B,所以也就共用x变量。且运行的是run函数里面的程序。

场景2:解决X变量被共用问题:

方法1:将int x=0;放入到run()函数中,此时,每个线程,都是从x=0开始执行;

方法2:创建多个B类的实例,比如b,b1,各自创建对应的线程进行处理,此时,两个线程互不干涉,代码如下

运行结果如下:

[当前线程]----------two=====实例变量的值----x=1

[当前线程]----------one=====实例变量的值----x=1

[当前线程]----------one=====实例变量的值----x=2

[当前线程]----------one=====实例变量的值----x=3

[当前线程]----------two=====实例变量的值----x=2

[当前线程]----------one=====实例变量的值----x=4

[当前线程]----------one=====实例变量的值----x=5

[当前线程]----------two=====实例变量的值----x=3

[当前线程]----------two=====实例变量的值----x=4

[当前线程]----------two=====实例变量的值----x=5

场景3:我们计划共同使用X,但是线程之间的运行需要先得到的运行结束后,后续的进程才能获得使用权,此时我们需要使用synchronized关键字来处理了代码如下。

运行结果如下

[当前线程]----------one=====实例变量的值----x=1

[当前线程]----------one=====实例变量的值----x=2

[当前线程]----------one=====实例变量的值----x=3

[当前线程]----------one=====实例变量的值----x=4

[当前线程]----------one=====实例变量的值----x=5

[当前线程]----------two=====实例变量的值----x=6

[当前线程]----------two=====实例变量的值----x=7

[当前线程]----------two=====实例变量的值----x=8

[当前线程]----------two=====实例变量的值----x=9

[当前线程]----------two=====实例变量的值----x=10

分析总结:我们在这里看到运行结果从1-10,但是运行过程中,是线程th1结束后,再开始th2。因为加了synchronzied,实现了同步,并且该对象锁对应的对象只有一个,那就是b,所以当第一个线程锁住了b,而第二个线程里面也是通过b去访问run()方法,所以必须等第一个线程执行完对象的方法时才能获得对象锁。

下一篇文章我们详细分析synchronized(同步)的概念。

先来一个总结:

1. java中的每个对象都有一个锁,当访问某个对象的synchronized方法时,表示将该对象上锁,此时其他任何线程都无法在去访问该syncronized 方法了,直到之前的那个线程执行方法完毕后,其他线程才有可能去访问该synchronized方法。

2.如果一个对象有多个synchronized方法,某一时刻某个线程已经进入到某个synchronzed方法,那么在该方法没有执行完毕前,其他线程无法访问该对象的任何synchronzied 方法的,但可以访问非synchronzied方法。

3.如果synchronized方法是static的,那么当线程访问该方法时,它锁的并不是synchronized方法所在的对象,而是synchuronized方法所在对象的对应的Class对象,

因为java中无论一个类有多少个对象,这些对象会对应唯一一个Class 对象,因此当线程分别访问同一个类的两个对象的static,synchronized方法时,他们的执行也是按顺序来的,也就是说一个线程先执行,一个线程后执行。

时间: 2024-10-28 23:07:27

Java多线程理解(线程安全)的相关文章

JAVA多线程之线程间的通信方式

一,介绍 本总结我对于JAVA多线程中线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码. 二,线程间的通信方式 ①同步 这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信. 参考示例: public class MyObject { synchronized public void methodA() { //do something.... } synchronized public void methodB()

关于Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇质量高的博文)

Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇质量高的博文) 前言:在学习多线程时,遇到了一些问题,这里我将这些问题都分享出来,同时也分享了几篇其他博客主的博客,并且将我个人的理解也分享给大家. 一.对于线程同步和同步锁的理解(注:分享了三篇高质量的博客) 以下我精心的挑选了几篇博文,分别是关于对线程同步的理解和如何选择线程锁以及了解线程锁的作用范围. <一>线程同步锁的选择 1. 这里我推荐下Java代码质量改进之:同步对象的选择这篇博文. 2. 以上推荐的博文是以卖火车票为例

Java多线程之线程结束清理

该事例说明了清理工作必须要放在finally块中 package Thread.Interrupting; import java.util.concurrent.TimeUnit; class NeedsCleanup { private final int id; public NeedsCleanup(int ident) { id = ident; System.out.println("NeedsCleanup " + id); } public void cleanup()

Java多线程之线程中断

该例子说明,Sleep可以被中断,但是I/O和synchronized不能被中断. package Thread.Interrupting; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; imp

java多线程之线程的同步与锁定(转)

一.同步问题提出 线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 例如:两个线程ThreadA.ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据. publicclass Foo { privateint x = 100; publicint getX() { return x;     } publicint fix(int y) {         x = x - y; return x;     } } publicclass MyRunnable i

java多线程之 ---- 线程死锁

java多线程之线程死锁 产生死锁的主要原因: 因为系统资源不足. 进程运行推进的顺序不合适. 资源分配不当等. 如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁.其次, 进程运行推进顺序与速度不同,也可能产生死锁. 产生死锁的四个必要条件:  互斥条件:一个资源每次只能被一个进程使用. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放. 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺. 循环等待条件:若干进

java多线程之 ---- 线程同步

java多线程之线程同步 线程同步 定义:同步是指在同一时间段内只能运行一个线程. 分类:同步方法.同步块. 作用:安全解决共享问题. 同步块: 语法: synchronized (同步对象) { 需要同步的代码; } 例子: public class ThreadDemo implements Runnable{ private int ticket = 5; public void run(){ for(int i=1;i<=5;i++){ synchronized (this){ if(t

Java多线程之线程的同步

Java多线程之线程的同步 实际开发中我们也经常提到说线程安全问题,那么什么是线程安全问题呢? 线程不安全就是说在多线程编程中出现了错误情况,由于系统的线程调度具有一定的随机性,当使用多个线程来访问同一个数据时,非常容易出现线程安全问题.具体原因如下:   1,多个线程同时访问一个数据资源(该资源称为临界资源),形成数据发生不一致和不完整.   2,数据的不一致往往是因为一个线程中的多个关联的操作(这几个操作合成原子操作)未全部完成. 关于线程安全问题,有一个经典的情景:银行取钱.代码如下: /

Java多线程之线程的控制

Java多线程之线程的控制 线程中的7 种非常重要的状态:  初始New.可运行Runnable.运行Running.阻塞Blocked.锁池lock_pool.等待队列wait_pool.结束Dead 如果将"锁池"和"等待队列"都看成是"阻塞"状态的特殊情况,那么可以将线程归纳为5个状态: 新建,就绪,运行,阻塞,死亡. ┌--------------------< 阻塞 ↓                    (1)(2)(3)  

Java多线程之线程的通信

Java多线程之线程的通信 在总结多线程通信前先介绍一个概念:锁池.线程因为未拿到锁标记而发生的阻塞不同于前面五个基本状态中的阻塞,称为锁池.每个对象都有自己的锁池的空间,用于放置等待运行的线程.这些线程中哪个线程拿到锁标记由系统决定.前面我们也有T到死锁的概念,线程互相等待其他线程释放锁标记,而又不释放自己的:造成无休止地等待.当出现死锁的时候,我们应该如何解决呢?通过线程间的通信解决. 线程间通信: 多线程之间的通信有2种方式,第一种是使用object类的几个方法,第二种是使用条件变了来控制