2

在java中,我的客户端有2个线程,一个是控制网络流,另一个是处理消息,绘制游戏等。我想做的是当数据包到来时,网络线程将调用 messageReceived 方法游戏线程,包含消息作为参数。如果我将函数 messageReceived 设置为同步并且在 messageReceived 函数结束之前依次有 2 个数据包,它会阻塞网络线程,或者它没有阻塞并且我的数据包丢失,因为网络线程无法调用已经被使用的 messageReceived 函数通过游戏线程?

4

6 回答 6

1

当您使用 synchronized 关键字同步代码部分时,当另一个线程进入想要访问该部分时,它将阻塞,直到它可以访问。

于 2013-05-03T17:49:00.427 回答
0

正确,您正在阻塞 IO 线程。您只想在 messageReceived() 上做一些简单的工作,因为……也许只在某种 FIFO 中排队消息,以便处理线程稍后处理。您的同步块应该尽可能小。

于 2013-05-03T17:50:29.157 回答
0

如果一个线程调用一个类中的同步方法,所有其他线程将被阻止调用该类中的任何同步方法,因为对象锁不可用。如果您的 messageReceived 不适用于任何共享资源,请使其保持非同步。如果它正在使用一些共享资源,则尝试通过将同步代码包装在同步块中来最小化同步代码。

于 2013-05-03T17:50:49.000 回答
0

如果您使用更主流的设计模式(例如观察者模式),听起来您正在尝试解决一个可以轻松避免的问题。http://en.wikipedia.org/wiki/Observer_pattern

于 2013-05-03T17:51:45.633 回答
0

是的,synchronized如果隐式锁已被另一个线程锁定,则阻塞一个线程。但是有一个非阻塞的替代方案 -java.util.concurrent.locks.Lock更灵活

Lock.tryLock()
  • 只有在调用时它是空闲的,才获取锁

Lock.tryLock(long time, TimeUnit unit)
  • 如果在给定的等待时间内空闲并且当前线程没有被中断,则获取锁。
于 2013-05-03T17:53:53.477 回答
0

它很容易概念化,但我更像是一个视觉化的人。这里有一些代码很久以前就帮助我理解了 excatly syncorized 做了什么以及它是如何工作的。如果您观察输出,您将在将同步属性添加到打印功能时看到,您永远不会看到 As 和 Bs 混合。但是当你删除它时,你会看到一个非常不同的输出。一旦你看到它,它应该是直截了当的。

public class Main {
    public static void main(String[] args) {
        (new ThreadA()).start();
        (new ThreadB()).start();
    }

    // try it with removing the synchronized:  public static void print(String str) {
    public static synchronized void print(String str) {
        for(int i = 0; i<100; i++)
            System.out.print(str);
        System.out.println();
    }

    public static class ThreadA extends Thread {
        public void run() {
            while(true) {
                print("A");
            }
        }
    }
    public static class ThreadB extends Thread {
        public void run() {
            while(true) {
                print("B");
            }
        }
    }
}
于 2013-05-03T17:58:35.440 回答