同步阻止?

时间:2013-05-03 17:45:51

标签: java synchronized

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

6 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

正确,您在IO线程上阻止了。你只想对messageReceived()做轻量级的工作......因为这可能只是将消息排队在某种FIFO中,以便稍后处理线程处理。您的同步块应尽可能小。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

听起来你正试图解决一个问题,如果你使用了更为主流的设计模式,如观察者模式,这个问题很容易避免。 http://en.wikipedia.org/wiki/Observer_pattern

答案 4 :(得分:0)

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

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

Lock.tryLock(long time, TimeUnit unit)
  • 获取锁定,如果它在给定的等待时间内是空闲的,并且当前线程没有被中断。

答案 5 :(得分:0)

它易于概念化,但更多的是视觉人。继承了一些代码,这些代码很久以前就帮助我理解了什么令人兴奋地合成了它以及它是如何工作的。如果您观察输出,您将看到将同步属性添加到您从未看到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");
            }
        }
    }
}