精华内容
下载资源
问答
  • Java多线程安全问题

    2021-02-28 14:02:05
    上一次我们说到在卖票问题中如果不将总票数设置为static静态变量,就会出现错票,即同样一张票会出售次。在今天的问题中,我们继续通过卖票问题来进行研究。我们在每一个线程进行判断条件后让线程睡眠一段时间(让...

    上一次我们说到在卖票问题中如果不将总票数设置为static静态变量,就会出现错票,

    即同样一张票会出售多次。

    在今天的问题中,我们继续通过卖票问题来进行研究。

    我们在每一个线程进行判断条件后让线程睡眠一段时间(让判断条件与数据操作之间相隔一段时间),看看会有什么效果?

    48b08b6a11637fbe955c427ff39151c3.png

    运行结果:

    ba62a4c22218aafa21008c922b147a03.png

    通过运行结果我们可以发现有出售第0张票和第-1张票的情况 ,这是为什么呢?

    是因为当有多个线程对一个共享数据进行操作时,可能会出现多线程的安全问题

    这也是我们今天研究的主题。

    当遇到这样的多线程安全问题时,我们可以通过synchronized关键字将它解决。

    synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

    1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;

    2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;

    3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;

    4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

    我们用synchronized关键字修饰一个代码块,将if判断语句“包”起来--->放入代码块中,再次运行

    67e83663fa0e53d8423c349620183f30.png

    结果如下:

    2574c0e0a399f2641877ad8e17a9ca6e.png

    我们可以看出,没有再发生出售第0,-1张票的情况。

    这是因为我们使用了synchronized关键字,使得一个线程在调用此同步锁的时候,将对象锁锁住(拥有对象锁)

    注意,这里锁的是作为对象锁的对象,并不是代码块,切记切记......

    线程拥有对象锁即只有该线程在执行完代码块中的内容后,将对象锁释放,其它线程才能拥有此对象锁,执行代码快中的内容,

    若该线程没有将对象锁释放,则其它线程便只能等待,等到该线程执行完代码块中内容后将锁释放,然后其它线程拥有此对象锁,进而执行代码快中的内容。

    若没有synchronized关键字,则假设此时总票数ticket为1,A线程此时获得CPU执行权,通过判断ticket=1 > 0,进入if语句,然后睡眠。(此时ticket没有减1,仍为1)

    A线程进入睡眠后,B线程获得CPU执行权,通过判断ticket=1 > 0,进入if语句,然后睡眠。

    A线程苏醒后,进行ticket--操作,此时ticke输出t为1,之后ticket=0,通过判断ticket=0 > 0失败,不执行if语句,进而退出while循环,执行完毕。

    B线程苏醒后,此时ticket为不为1,为0,则ticket进行--操作后,输出为0,之后ticket=-1,通过判断ticket= -1 > 0失败,不执行if语句,进而退出while循环,执行完毕。

    若程序主线程中还定义了第三个线程,则如线程B,输出为-1 ----->这就是出现出售第0,-1张票情况的原因。

    若加了synchronized代码块,则,A线程在执行完代码块中的内容后(进行ticket-1操作后),

    其它线程才能根据ticket进行判断,若不满足条件,就会结束循环,执行完毕。就不会发生上述出售第0,-1张票的情况

    从而解决多个线程对一个共享数据进行操作时出现的安全问题......

    接下来我们使用两个线程分别调用同步代码块和同步方法

    811585b8872c6afba1ef5b4d36c6712e.png

    4e0757ce962feb20c38ea416319fb7b0.png

    68b05150b8733edd5636ec707eb4811c.png

    运行结果仍会有出售第0张票的情况,,小伙伴们可以自己试一下。

    这是因为两个线程的对象锁是不同的,A线程的对像锁是obj,而B线程的对像锁是this,

    (这里需要注意的是,B线程调用了同步方法【同步方法的对像锁是this】

    而【静态同步方法的对象锁是当前类的字节码文件对象】,定义方法--->【类.class | 对象.getClass()】)

    即A线程虽然将它的对象锁(obj)锁住,但并不影响B线程拥有它自己的对像锁(this),

    它们的对像锁是不同的,结果很明显--->这样并不能解决多线程安全问题

    当我们将同步代码块的对像锁设置为this时,两个线程的对像锁相同,便能解决多线程安全问题

    使用静态同步方法与同步方法类似,将同步代码块的对像锁设置为  类.class  或者  对象.getClass(),也能解决多线程安全问题。

    最后再说两个相关知识点:

    同步方法与普通方法可以同时调用

    synchronized获得的锁是可重入的

    一个同步方法可以调用另外一个同步方法,一个线程已经拥有某个对象的锁,再次申请的时候仍然会得到该对象的锁.

    【具体理解为:在使用synchronized时,当一个线程得到一个对象锁后,再次请求此对象锁时,是可以再次得到该对象的锁的。

    也就是说在一个synchronized方法或块的内部调用本类的其他synchronized方法或块时,是永远可以得到锁的。】

    这里需要注意的是,子类的同步方法中也可以调用父类的同步方法(通过super关键字)。

    展开全文
  • 多线程情况下,mysql_init会设置线程的私有数据,如果不注意,则会在mysql_real_connect时出现段错误。错误如下:void* func(void* arg){MYSQL* mysql = (MYSQL *)arg;mysql_real_connect(mysql, “127.0.0.1″, ...

    多线程情况下,

    mysql_init会设置线程的私有数据,如果不注意,则会在mysql_real_connect时出现段错误。

    错误如下:

    void* func(void* arg)

    {

    MYSQL* mysql = (MYSQL *)arg;

    mysql_real_connect(mysql, “127.0.0.1″, “root”, “123456″, “chen”, 1234, NULL, 0);

    mysql_close(mysql);

    return (void *)0;

    }

    int main()

    {

    MYSQL mysql;

    if (NULL == mysql_init(&mysql))

    {

    return -1;

    }

    pthread_t thread;

    pthread_create(&thread, NULL, func, &mysql);

    pthread_join(thread, NULL);

    return 0;

    }

    出现段错误:

    #0 0×0000000000417db2 in my_stat () (gdb) bt #0 0×0000000000417db2 in my_stat () #1 0×00000000004169f4 in my_read_charset_file () #2 0×0000000000416cb2 in init_available_charsets () #3 0×00000000004170ea in get_charset_by_csname () #4 0×0000000000405fda in mysql_init_character_set () #5 0×0000000000407024 in mysql_real_connect ()

    问题原因

    源代码中,Mysql_init()会初始化一些线程私有数据。 Mysql_init()中调用my_thread_init(), 其中设置线程私有数据。

    mysql_init()不是完全线程安全的,但是只要成功调用一次就后就线程安全了,如果有多线程并发使用mysql_init(),建议在程序初始化时空调一次mysql_init(),他的这点特性很像qsort() 。

    解决办法

    所以可以这么使用:

    (1)mysql_init()和mysql_real_connect()放在一起:

    (2)调用mysql_thread_init()和mysql_thread_end()来初始化和线程相关的数据

    如:

    void* func(void* arg)

    {

    MYSQL* mysql = (MYSQL *)arg;

    mysql_thread_init();

    mysql_real_connect(mysql, “127.0.0.1″, “root”, “123456″, “chen”, 1234, NULL, 0);

    mysql_close(mysql);

    mysql_thread_end();

    return (void *)0;

    }

    展开全文
  • 问题,如题!我先说我目前的方案(我感觉不靠谱,但是又不知道如何测试):public class SaveDatabasePlanCache {private static Integer vehicleSum=0;public static Integer getVehicleSum() {return vehicleSum;}...

    问题,如题!

    我先说我目前的方案(我感觉不靠谱,但是又不知道如何测试):

    public class SaveDatabasePlanCache {

    private static Integer vehicleSum=0;

    public static Integer getVehicleSum() {

    return vehicleSum;

    }

    public synchronized static void setVehicleSum(Integer vehicleSum) {

    SaveDatabasePlanCache.vehicleSum = vehicleSum;

    }

    }

    测试方案:

    TestThread t1=new TestThread("线程1: ");

    TestThread t2=new TestThread("线程2: ");

    TestThread t3=new TestThread("线程3: ");

    TestThread t4=new TestThread("线程4: ");

    ExecutorService service=Executors.newFixedThreadPool(4);

    service.submit(t1);

    service.submit(t2);

    service.submit(t3);

    service.submit(t4);

    线程代码:

    public void run() {

    int sum=0;

    boolean flag=true;

    while(flag){

    sum=SaveDatabasePlanCache.getVehicleSum();

    if(sum==10000){

    System.out.println(new Date().toLocaleString()+" "+title+"不执行");

    flag=false;

    }else{

    SaveDatabasePlanCache.setVehicleSum(sum+1);

    System.out.println(new Date().toLocaleString()+" "+title+SaveDatabasePlanCache.getVehicleSum());

    }

    }

    }

    上面是我对静态变量的线程安全方案,就是在设置值的时候开启一个线程同步锁的机制,不知道这样是否有效,我在测试的时候,程序死锁过。

    请问有什么有效的方法可以测试吗或者解决我当前的问题,谢谢!

    展开全文
  • 有个项目用到多线程多线程里有记录日志功能,用到localtime获取时间,一开始用localtime_r函数来代替localtime函数,因为localtime函数返回值里有个全局的变量,而localtime_r函数有读写保护,但是在某个arm 平台...

    有个项目用到多线程,多线程里有记录日志功能,用到localtime获取时间,一开始用localtime_r函数来代替localtime函数,因为localtime函数返回值里有个全局的变量,而localtime_r函数有读写保护,但是在某个arm 平台下跑了一段时间发现突然时区出现混乱,在网上查到有篇文章说localtime_r函数里牵涉到时区时有个全局变量,线程也不安全,没办法只能自己重新定义写一个函数,好在网上有人贡献,参考改下,再跑一段时间,没有出现问题。

    展开全文
  • Java多线程(多线程基本操作,多线程安全问题等)

    多人点赞 热门讨论 2021-08-07 22:49:21
    Java创建多线程前言一、创建线程四种方式1)继承Thread2)调用Runnable3)匿名内部类4)使用lambda表达式来创建二、了解Thread 类2.1Thread的常见的构造方法2.2Thread的几个常见的属性 前言 在Java中有,有一个...
  • 同步锁-线程安全问题解决方案

    万次阅读 多人点赞 2021-03-21 15:12:05
    我们如何判断程序有没有可能出现线程安全问题,主要有以下三个条件: 在多线程程序中 + 有共享数据 + 多条语句操作共享数据 多线程的场景和共享数据的条件是改变不了的(就像4个窗口一起卖100张票,这个是业务) 所以思路...
  • 多线程高阶 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录多线程高阶前言本节目标一、常见的锁策略1.1 乐观锁1.2 悲观锁1.3 读写锁1.4 公平锁与非公平锁1.5 自旋锁(Spin Lock)1.6...
  • 实例探索多线程安全问题1.利用继承Thread类的方式卖电影票2.实现Runnable接口的方式卖电影票3.线程安全问题的实例发生 临近春节,各大电影院都在筹备准备上映贺岁大片。假设某家电影院持有唐探3的票100张,而且它...
  • 众所周知,多线程会造成线程安全问题,那么多线程为什么会导致线程安全问题呢? 一:首先了解jvm内存的运行时数据区 1.堆区:存储对象实例(和实例变量),数组等 2.java虚拟机栈(方法·栈),存放方法声明,...
  • HashMap的线程不安全主要体现在下面两...常被问到的HashMap和Hashtable的区别1、线程安全两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全。Hashtable的实现方法里面都添加了synchronized关键字来确...
  • import java.util.function.ObjDoubleConsumer; public class WindowTest1 { public static void main(String[] args) { window1 p = new window1(); Thread t1 = new Thread(p);... Thread t2 = new Thread(p);...
  • 多线程调用static方法线程安全问题

    千次阅读 2021-11-10 15:44:42
    最近在工作中遇到了线程安全问题,是在一个方法中调用了静态方法解析Date的字符串。 因为 SimpleDateFormat这个类是线程不安全的,所以不能在静态方法中定义全局的成员变量。 @Test void contextLoads() { ...
  • @Override public void run() { while (true) { synchronized (obj) {//锁(同步监视器)-->任何一个类的对象都可以是锁 if (ticket > 0) {//锁-->要求多线程共用同一个锁 try { Thread.sleep(100); } catch ...
  • Java多线程线程安全问题1、线程安全1.1、什么是线程安全?1.2、什么情况下会出现线程安全问题,怎么避免?1.3、一共有哪几类线程安全问题?1.3.1、运行结果错误1.3.2、活跃性问题1.3.3、对象发布和初始化的时候的...
  • 简单讨论一下在一个类中使用静态字段(static field)和静态方法(static method)是否会有线程安全问题。我们在知道, 静态字段(static field)和静态方法(static method)的调用是通过类来调用。静态方法不对特...
  • 超买,超卖,秒杀等问题就是线程安全问题。 本质 个线程操作同一个共享变量。 流程 代码为 A->B->C A处有判断,B处有相关业务,C处有共享变量数据改变。 在某个时间,有三个线程: 1、线程1首先来到了A代码...
  • LinkedList线程安全问题

    2021-02-12 22:51:40
    Java中LinkedList是线程不安全的,那么如果在多线程程序中有多个线程访问LinkedList的话会出现什么问题呢?抛出ConcurrentModificationExceptionJDK代码里,ListItr的add(), next(), previous(), remove(), set()...
  • java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同《java并发编程实践》中所说:写道给线程安全下定义比较困难。存在很多种定义,如:“一个类在可以被多个...
  • Java中线程部分知识中,售票程序非常经典。程序中也有一些问题存在!需求:模拟3个窗口同时在售100张票。问题1:为什么100张票被卖出了300张票?原因:因为tickets是非静态的,非静态的...线程安全问题的解决方案:...
  • 线程安全问题 解决线程安全问题 1.首先观察线程不安全问题 如下代码:本来预期结果n = 0;但是因为线程的安全问题,导致会出现其他结果,只有有不是预期结果的情况出现,我们就不能说它是安全的; 因为n++和n–的...
  • 线程安全问题和解决方案什么是线程安全解决方案:线程同步方式一、同步代码块方式二、同步方法方式三:显式Lock锁 什么是线程安全 线程安全:如果有个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次...
  • 线程安全问题) 导航不迷路: 程序、进程以及线程的爱恨情仇 最简单实现多线程的方法(Thread) 简单易懂的多线程(通过实现Runnable接口实现多线程) 常用获取线程基本信息的方法(新手专属) 文章目录多线程,...
  • 请问多线程数据库程序怎么保证线程安全问题是这样子:多台电脑(或一台电脑中的多个线程)分别从服务器读取数据,并将数据修改后写回数据库。但如果在写入服务器时服务器内数据和本机读取时不一致,则写入操作被拒绝。...
  • JAVA中的多线程并发运行安全问题

    千次阅读 热门讨论 2021-03-19 17:58:27
    JAVA中的多线程并发运行安全问题 1.什么是多线程并发运行安全问题? 当多个线程并发操作一个数据时,由于线程操作的时间不可控的原因,可能会导致操作该数据时的过程没有按照程序设计的执行顺序运行,导致操作后数据...
  • 前言在提到多线程的时候我们大都会想到ArrayList 与 HashMap,这两个类型都是非线性安全的!在多个线程同时操作改集合对象时,会出现哪些问题呢?在传统的集合包内的集合类到底为什么线程非安全呢?在新的JUC包类又...
  • 使用flask-sqlalchemy写代码码到一半,突然想到,Session是否是线程安全的?于是上官方文档,答案是否!那问题来了,怎么破?因为它会牵涉到多线程情况下,调用rollback导致的不可预期影响。官网给了两个方案:使用 ...
  • 关于多线程安全问题以及解决方法 线程不安全   线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据并不是你所想要的。下面举例说明: public class Demo { /** * 线程不安全 ...
  • 问题集合多线程常见问题之多线程安全问题多线程常见问题之多线程乱跑传参问题 多线程常见问题之多线程安全问题 明确一点,不操作共享变量就不会有线程安全问题。 有线程安全问题,什么时候加锁 共享数据有可能同时被...
  • JavaFX 中使用多线程与保证 UI 线程安全JavaFX 中使用多线程JavaFX 中保证 UI 线程安全总结与补充   JavaFX 中的 UI 和大多数其它的编程语言一样,是单线程的。前人很早就已经多次尝试在 UI 上使用多线程,大多都...
  • 线程安全的链表接下来写一个线程安全的链表双链表中每个节点都有一个指针指向列表中下一个节点,还有一个指针指向前一个节点。其中不变量就是节点A中指向“下一个”节点B的指针,还有前向指针。为了从列表中删除一个...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 850,595
精华内容 340,238
关键字:

多线程安全问题