对于线程安全,大家都知道使用synchronized控制访问的资源,有变量安全、方法安全、块安全。
我这里有个需求是这样的,我这里作为服务端有很多客户端与我进行交互,服务端也会主动发消息给客户端,但是要求每次交互时只能有一个用户。也就是说发送一组信息、等待信息、处理信息返回时这个链路只能有一个人使用。
也许大家马上会想到这样写:
synchronized (ThreadT.devIpsIsCanUse) { }
但是一旦这样写,在安全块内devIpsIsCanUse这个变量不能再被其他用户访问,因为此时这个资源是线程安全的,只能有一个线程进行访问。
如果此时我想访问不同线路,也是不行,因为一旦访问devIpsIsCanUse这个资源就会进行等待
可以这样写进行测试:
package com.hoo.mina; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class ThreadT { public static Map<String, Boolean> devIpsIsCanUse = new ConcurrentHashMap<String, Boolean>(); public static void main(String[] args) { devIpsIsCanUse.put("testKey1", true); devIpsIsCanUse.put("testKey2", true); new Thread(new ServiceImpl(1)).start(); new Thread(new ServiceImpl(2)).start(); } } class ServiceImpl implements Runnable { public int w; public ServiceImpl(int w) { this.w = w; } public void run() { while (true) { try { synchronized (ThreadT.devIpsIsCanUse) { if (ThreadT.devIpsIsCanUse.get("testKey" + w)){ ThreadT.devIpsIsCanUse.put("testKey" + w, false); System.out.println(w + ":我来了:" + this.toString()); Thread.sleep(2 * 1000); System.out.println(w + ":我走了:" + this.toString()); ThreadT.devIpsIsCanUse.put("testKey" + w, true); } } } catch (Exception e) { e.printStackTrace(); } } } }
运行后发现,对于资源1和资源2的访问是排队的,这明显不符合要求
改动很简单,只要把处理的代码放到安全块外即可,因为对于是否使用的判断处理是非常快的,在用就继续循环否则向下走即可
package com.hoo.mina; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class ThreadT { public static Map<String, Boolean> devIpsIsCanUse = new ConcurrentHashMap<String, Boolean>(); public static void main(String[] args) { devIpsIsCanUse.put("testKey1", true); devIpsIsCanUse.put("testKey2", true); new Thread(new ServiceImpl(1)).start(); new Thread(new ServiceImpl(2)).start(); } } class ServiceImpl implements Runnable { public int w; public ServiceImpl(int w) { this.w = w; } public void run() { while (true) { try { synchronized (ThreadT.devIpsIsCanUse) { if (ThreadT.devIpsIsCanUse.get("testKey" + w)){ ThreadT.devIpsIsCanUse.put("testKey" + w, false); }else{ Thread.sleep(200); continue; } } System.out.println(w + ":我来了:" + this.toString()); Thread.sleep(2 * 1000); System.out.println(w + ":我走了:" + this.toString()); ThreadT.devIpsIsCanUse.put("testKey" + w, true); } catch (Exception e) { e.printStackTrace(); } } } }
此时我们看到打印信息是资源1和资源2的访问是同时的,但是对于资源1的访问是需要排队的
那么此时我又在想,如果不加休眠,多个线程同时访问资源1时,如果A线程开始访问了且一直轮询,此时B再来访问,那么两个线程进安全块的顺序是必须A走完才能是B吗?
其实不是的在进安全块时,线程A和线程B是竞争的,而不是排队,可以这些看一下:
package com.hoo.mina; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class ThreadT { public static Map<String, Boolean> devIpsIsCanUse = new ConcurrentHashMap<String, Boolean>(); public static void main(String[] args) { devIpsIsCanUse.put("testKey1", true); new Thread(new ServiceImpl(1)).start(); new Thread(new ServiceImpl(1)).start(); new Thread(new ServiceImpl(1)).start(); new Thread(new ServiceImpl(1)).start(); } } class ServiceImpl implements Runnable { public int w; public ServiceImpl(int w) { this.w = w; } public void run() { while (true) { try { synchronized (ThreadT.devIpsIsCanUse) { if (ThreadT.devIpsIsCanUse.get("testKey" + w)){ ThreadT.devIpsIsCanUse.put("testKey" + w, false); }else{ Thread.sleep(500); System.out.println(w + ":被占中:" + this.toString()); continue; } } System.out.println(w + ":我来了:" + this.toString()); try { Thread.sleep(1 * 1000); } catch (Exception e) { } System.out.println(w + ":我走了:" + this.toString()); ThreadT.devIpsIsCanUse.put("testKey" + w, true); } catch (Exception e) { e.printStackTrace(); } } } }
看一下打印:
1:我来了:ServiceImpl@14318bb 1:被占中:ServiceImpl@1a758cb 1:被占中:ServiceImpl@1b67f74 1:我走了:ServiceImpl@14318bb 1:被占中:ServiceImpl@1b67f74 1:我来了:ServiceImpl@1b67f74
可以明显看到他们是竞争关系
请您到ITEYE网站看原创,谢谢!
http://cuisuqiang.iteye.com/ !
自建博客地址:http://www.javacui.com/ ,内容与ITEYE同步!
相关推荐
然而,多线程环境下的资源共享往往伴随着数据竞争问题,这时就需要引入线程同步机制,以确保共享资源的安全访问。本文将深入探讨多线程同步中的“临界区”概念及其在实际应用中的示例。 临界区是一种线程同步原语,...
总结,多线程ADO安全访问SQL涉及到数据库并发控制、事务管理、线程同步和资源管理等多个方面。开发者必须理解这些概念并正确实施,以确保应用程序的稳定性和数据的准确性。通过合理的设计和编程实践,可以在提高性能...
在Python编程中,多线程是一种并发执行任务的机制,尤其在处理I/O密集型任务如网络请求时,能够显著提高程序效率。...在编写这样的程序时,我们需要关注线程安全、资源管理以及并发控制,以确保程序的正确性和高效性。
例如,`Mutex`允许跨进程的互斥访问,而`Semaphore`则可以控制同时访问资源的线程数量。 测试这个多线程互斥的例子,我们可以创建多个线程,每个线程分别调用`Increment`或`Decrement`方法,然后观察`GetValue`返回...
本文将深入探讨多线程环境下如何管理和控制资源共享,主要关注`synchronized`关键字、`Runnable`接口以及`Thread`类的使用。 首先,让我们了解什么是多线程。多线程是指在一个进程中同时执行多个线程,每个线程都有...
### Delphi多线程的安全问题分析及解决 #### 摘要 本文深入探讨了Delphi环境下多线程运行过程中可能遇到的安全问题及其解决方案。在Windows操作系统中,多线程技术因其高效性和灵活性而被广泛应用于软件开发之中。...
总的来说,“易语言完美多线程控制例子”是一个极好的学习资源,它让我们有机会实践易语言的多线程编程,掌握如何在实际项目中应用这些技术。无论是对于初学者还是经验丰富的开发者,理解并掌握多线程控制都是提升...
多线程安全问题主要出现在共享资源的访问上。当多个线程同时访问相同的资源(共享变量)时,如果没有正确的同步机制,可能会导致不可预测的结果。 - **原因**:存在共享数据,并且存在对共享数据的多条操作路径,...
2. **线程同步**:在多线程环境中,防止数据竞争和确保资源安全访问是至关重要的。C#提供了多种同步机制,如`Mutex`、`Semaphore`、`Monitor`和`lock`关键字。模板可能内置了这些同步工具的使用,减少了因不当同步...
在这个"操作多线程删除数据库表,以及控制listbox多线程呈现"的小程序中,我们将探讨如何利用多线程来处理数据库操作和UI更新。 1. **多线程基础**:多线程是指在一个应用程序中同时运行多个独立的执行流。在.NET ...
总之,WinCe上的多线程访问WinForm控件需要开发者深入理解线程同步、UI线程安全以及异步编程。遵循上述原则,可以有效防止异常,提高程序的稳定性和用户体验。在实际编程过程中,应始终牢记,UI控件的修改应由创建它...
3. **线程安全**:在多线程环境中,对SQLite的读写操作需要确保线程安全。否则,多个线程同时访问数据库可能导致数据损坏或不一致。C#中的`lock`关键字是一种同步机制,可以防止多个线程同时访问共享资源。 4. **...
本篇将深入探讨易语言中如何实现多线程控制以及线程数量的管理。 在易语言中,线程用于在单个进程中同时执行多个独立的代码段,从而提高程序的执行效率。创建线程的基本步骤包括定义线程函数、创建线程对象和启动...
为了确保线程安全,即在多线程环境中正确管理和访问资源,.NET提供了一系列工具和技术。其中,`lock`关键字、`Monitor`类和`Mutex`类是最常用的方法。 - **lock关键字**:这是一种简单的同步机制,用于保护对临界区...
- 在读多写少的情况下,`ReaderWriterLockSlim`能提高性能,因为多个读取者可以同时访问资源,只有写入者需要独占锁。 - 但是,使用这种同步机制需要谨慎,避免死锁和资源泄漏。 3. **Mutex 或 Semaphore** - 另...
总结来说,C#的多线程控制实例涉及创建线程、启动和停止线程、线程间的同步和通信,以及如何安全地管理线程。通过理解和熟练运用这些概念,开发者可以编写出高效、稳定的多线程程序。在实践中,要特别注意避免常见的...
4. **线程安全**:如果一个方法或数据结构在多线程环境下能正确工作,我们就称其为线程安全。线程安全可以通过设计、同步机制或使用线程安全的数据结构来实现。 在实践中,多线程编程还需要关注性能和资源消耗,...
1. **线程安全**:安全队列保证了在多线程环境下的并发访问是安全的,它内部实现了锁或者其他同步机制,避免了线程间的不协调操作。 2. **阻塞操作**:安全队列的插入(offer、put)和删除(poll、take)操作如果在...
在多线程环境中,当多个线程访问共享资源时,如果没有适当的同步机制,可能会导致数据不一致或竞态条件。Java提供了多种同步工具,如`synchronized`关键字、`wait()`, `notify()`, `notifyAll()`方法,以及`Lock`...
- 线程安全:需要确保在多线程环境下,程序的正确性和一致性,避免出现未预期的结果。 5. **文件"多线程控制.e"**: 这个文件很可能是易语言的一个示例程序,演示了如何在易语言中实现多线程控制。通过打开并学习...