栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Java多线程-线程安全计数器

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java多线程-线程安全计数器

两个线程都可以访问您的变量。

您看到的现象称为线程饥饿。输入代码的受保护部分后(很抱歉,我之前错过了它),其他线程将需要阻塞,直到持有监视器的线程完成(即, 释放
监视器时)。尽管可能希望当前线程将监视器传递给等待排队的下一个线程,但是对于同步块,java不保证线程下一个接收监视器的任何公平性或排序策略。
一个线程完全有可能(甚至有可能)释放并尝试重新获取监视器,以使其在等待了一段时间的另一个线程上获得它。

从Oracle:

饥饿描述了一种情况,即线程无法获得对共享资源的常规访问并且无法取得进展。当“贪婪”线程使共享资源长时间不可用时,就会发生这种情况。例如,假设一个对象提供了一个同步方法,该方法通常需要很长时间才能返回。如果一个线程频繁调用此方法,则也需要频繁同步访问同一对象的其他线程将经常被阻塞。

虽然您的两个线程都是“贪婪”线程的示例(因为它们反复释放并重新获取监视器),但从技术上讲,线程0首先启动,因此线程1处于饥饿状态。

解决方案是使用支持公平性的并发同步方法(例如ReentrantLock),如下所示:

public class ThreadsExample implements Runnable {    static int counter = 1; // a global counter    static ReentrantLock counterLock = new ReentrantLock(true); // enable fairness policy    static void incrementCounter(){        counterLock.lock();        // Always good practice to enclose locks in a try-finally block        try{ System.out.println(Thread.currentThread().getName() + ": " + counter); counter++;        }finally{  counterLock.unlock();        }     }    @Override    public void run() {        while(counter<1000){ incrementCounter();        }    }    public static void main(String[] args) {        ThreadsExample te = new ThreadsExample();        Thread thread1 = new Thread(te);        Thread thread2 = new Thread(te);        thread1.start();        thread2.start();   }}

请注意,在方法中删除了

synchronized
有利于ReentrantLock
的关键字。这种具有公平性策略的系统允许长时间等待的线程有机会执行,从而消除了饥饿。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/454253.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号