简体   繁体   English

锁定是否正确完成

[英]Is the lock being done correctly

I am reading a UDP feed then decoding it and writing to MSMQ(Message Queuing). 我正在读取UDP提要,然后对其进行解码并写入MSMQ(消息队列)。

I create a new thread that calls UDPReader. 我创建一个新的线程,调用UDPReader。 In turn UDPReader creates a threadpool and calls class ipaddrConnection. UDPReader依次创建一个线程池并调用类ipaddrConnection。 Run inside ipaddrConnection contains a while loop that continuously reads packets from the Multicast socket and pushes it to class parseUDP. 在ipaddrConnection内部运行,包含一个while循环,该循环不断从Multicast套接字读取数据包并将其推入parseUDP类。 From parseUDP it is decoded and finally pushed to the class that writes to MSMQ. 从parseUDP对其进行解码,最后将其推送到写入MSMQ的类。 I believe I am not locking the threads properly when it comes to the while loop in ipaddrConnection because threads are attempting to write to the same memory location in MSMQ. 我认为在ipaddrConnection中的while循环中,我无法正确锁定线程,因为线程正在尝试写入MSMQ中的相同内存位置。 I thought that by placing my lock in the while loop, each thread in the pool would have its own time in the "Critical Section" 1.receive a packet then 2.decode and write to MSMQ. 我认为,通过将我的锁置于while循环中,池中的每个线程在“关键部分”中都有自己的时间。1.接收数据包,然后2.解码并写入MSMQ。 I am still learning concurrency and looking for some help. 我仍在学习并发并寻求帮助。 I have provided a crash dump file that I don't understand how to properly read and my UDPReader and ipaddrConnection classes. 我提供了一个我不理解如何正确读取的故障转储文件以及UDPReader和ipaddrConnection类。 parseUDP calls a class to decode the packet and that class calls a MSMQ class to write to memory. parseUDP调用一个类来解码数据包,而该类调用一个MSMQ类来写入内存。 All of which are in my Critical Section. 所有这些都在我的关键部分。

class UDPReader implements Runnable
{
    private final String ip, socket, queue, threadName;
    private final JTextArea screen;

    UDPReader(String ip, String socket, String queue, String threadName, JTextArea screen) 
    {
        this.ip = ip;
        this.socket = socket;
        this.queue = queue;
        this.threadName = threadName;
        this.screen = screen;
    }

    public void run()
    {
        screen.append("Thread " + threadName + " running\n\n");
        ExecutorService executor = Executors.newFixedThreadPool(5);
        Runnable reader = new ipaddrConnection(ip, socket, queue);
        executor.execute(reader);
    }

}

public final class ipaddrConnection implements Runnable
{
    private final ReentrantLock lock = new ReentrantLock();
    byte[] bytes = new byte[(int)100000];
    InetAddress group; 
    MulticastSocket s;
    DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
    private String queue;

    public ipaddrConnection(String ip, String socket, String queue) {
        try {
            this.s = new MulticastSocket(Integer.parseInt(socket));
            this.group = InetAddress.getByName(ip);
            this.queue = queue;
        } catch (IOException ex) {
            Logger.getLogger(ipaddrConnection.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

        @Override
        public void run() {
            try {
                parseUDP p = new parseUDP(queue);
                s.joinGroup(group);
                s.setSoTimeout(95000);

                try{
                    while(true){
                        lock.lock();
                        s.receive(packet);
                        p.parseUDP(packet.getData());
                    } 
                }finally {
                    lock.unlock();
                }


             } catch (SocketException ex) {
                Logger.getLogger(ipaddrConnection.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(ipaddrConnection.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

}

Crash Report https://drive.google.com/file/d/0B4GWNCU6_CBlM2tJNGJqNzRVazg/view?usp=sharing 崩溃报告https://drive.google.com/file/d/0B4GWNCU6_CBlM2tJNGJqNzRVazg/view?usp=sharing

In your code, your locks don't do anything useful. 在您的代码中,锁没有任何用处。

Each thread has its own lock, so there can be more than one thread using the queue at a time (because Thread 1 locked Lock 1, and Thread 2 locked Lock 2, and there's nothing stopping them using the queue at the same time). 每个线程都有自己的锁,因此一次使用队列可以有多个线程(因为线程1锁定了锁1,线程2锁定了锁2,没有什么可以同时使用队列停止它们了)。

If you make the lock field static in your code, then the threads will all use the same lock. 如果在代码中将lock字段设置为static ,则线程将全部使用相同的锁。

You might still have problems, because threads never release the lock (unless they encounter an exception) so only one thread will be allowed to do work: 您可能仍然会遇到问题,因为线程从不释放锁(除非它们遇到异常),因此仅允许一个线程进行工作:

try{
    while(true){
        lock.lock();
        s.receive(packet);
        p.parseUDP(packet.getData());
    } 
}finally {
    lock.unlock();
}

Notice how the only way the thread can unlock the lock is if there's an exception? 请注意,如果存在异常,线程解锁锁的唯一方法是什么?

You might have wanted something more like this: 可能想要这样的东西:

while(true) {
    s.receive(packet);
    try {
        lock.lock();
        s.parseUDP(packet.getData());
    } finally {
        lock.unlock();
    }
}

- with this structure, threads will only hold the lock while they are parsing the packets, not while they are receiving packets. -采用这种结构,线程仅在解析数据包时才持有锁,而不是在接收数据包时才持有锁。 (I don't know whether this is what you actually want) (我不知道这是否是您真正想要的)

ExecutorService executor = Executors.newFixedThreadPool(5);
Runnable reader = new ipaddrConnection(ip, socket, queue);
executor.execute(reader);

This code is, in effect, single threaded since although the pool has five threads, you are using up only one. 该代码实际上是单线程的,因为尽管该池有五个线程,但是您只使用了一个线程。

  1. Having UDPReader implement Runnable and it's run() implementation is at the very least not idiomatic. 使UDPReader实现Runnable及其run()实现至少不是惯用的。
  2. As mentioned by immibis your lock objects are not shared between the threads and they don't provide the protection you are looking for. 如immibis所述,您的锁对象不在线程之间共享,并且它们不提供您想要的保护。
  3. You unlock only when you exit while (true) { ... } which is to say never. 只有在while (true) { ... }退出时才解锁,也就是说永远不会解锁。 With this in mind you may want to consider something like: 考虑到这一点,您可能需要考虑以下内容:

      public class UDPReader { ... UDPReader(String ip, String socket, String queue, String threadName, JTextArea screen, numberOfThreads) { ... this.numberOfThreads = numberOfThreads; this.lock = new ReentrantLock(); } public void run() { ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads); for (int i = 0; i < numberOfThreads; i++){ executor.execute(new ipaddrConnection(ip, socket, queue, lock)); } } } public final class ipaddrConnection implements Runnable { private lock ; ... public ipaddrConnection(String ip, String socket, String queue, ReentrantLock lock) { ... this.lock = lock; } @Override public void run() { ... while (true) { try { lock.lock(); s.receive(packet); p.parseUDP(packet.getData()); } finally { lock.unlock(); } } .... } } } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM