6

同步通过在方法名称前放置一个 Synchronized 关键字来提供对对象或方法的独占访问。如果两个或多个对方法的访问同时发生,我想给一个特定的访问更高的优先级怎么办?我们可以这样做吗?

或者只是我可能误解了 java 中同步的概念。请纠正我。我还有其他问题,

我们应该在什么要求下使方法同步?何时使方法同步?什么时候使块同步?另外,如果我们使方法同步,类也会同步吗?这里有点困惑。

请帮忙。谢谢。

4

4 回答 4

6

在并发包中,几乎所有你需要的多线程和同步都有一个解决方案,但是它需要你先考虑一下你要做什么。如果您只有一个非常基本的问题要解决,同步、等待和通知结构就像最基本的工具,但实际上大多数高级程序将(/应该)从不使用这些,而是​​依赖于 Concurrent 包中可用的工具。

你对线程的看法有点错误。没有更重要的线程,只有更重要的任务。这就是为什么 Java 清楚地区分线程、可运行对象和可调用对象的原因。

同步是一个防止多个线程进入特定代码部分的概念,这也是避免线程问题的最基本概念。如果多个线程访问某些数据,其中至少一个线程正在尝试修改该数据,则会出现这些问题。考虑一个由线程 A 读取的数组,同时由线程 B 写入。最终,线程 B 将写入线程 A 即将读取的单元格。现在由于线程的执行顺序未定义,线程 A 是否将读取旧值、新值或介于两者之间的东西也未定义。

围绕此访问的同步“锁定”是确保这种情况永远不会发生的一种非常粗暴的方式,并发包中提供了更复杂的工具,例如 CopyOnWriteArray,它通过为写入线程创建副本来无缝处理上述问题,所以线程 A 和线程 B 都不需要等待。其他工具可用于其他解决方案和问题。

如果您深入研究可用的工具,您很快就会发现它们非常复杂,使用它们的困难通常在于程序员而不是工具,因为已经投入了无数小时的思考、改进和测试。

编辑:澄清一下为什么即使您在线程上设置了任务的重要性:想象一条有 3 条车道的街道缩小到 1 条车道(同步块)和 5 辆汽车(线程)正在到达。让我们进一步假设有一个人(汽车调度员)必须定义哪些汽车获得第一行,哪些汽车获得其他行。由于只有一条车道,他最多只能将一辆车分配到第一排,其他车需要在后面。如果所有的汽车看起来都一样,他很可能会或多或少地随机分配订单,而已经在前面的汽车可能更可能留在前面,只是因为移动这些汽车会很麻烦。

现在假设一辆车的顶部有一个“美国总统在里面”的标志,所以调度员很可能会在他的决定中优先考虑那辆车。但即使标志在车上,他做出决定的原因也不是车(线程)的重要性,而是车内人(任务)的重要性。所以这个标志只是调度员的信息,这辆车运送更重要的人。然而无论这是否属实,调度员不能说(至少在没有检查的情况下不能),所以他只需要相信车上的标志。

现在,如果在另一种情况下,所有 5 辆汽车都有“President inside”标志,调度员没有办法决定哪一辆先去,他再次处于与所有汽车都没有标志的情况相同的情况全部。

于 2013-11-11T19:54:27.750 回答
5

不。遗憾的是,Java 同步和等待/通知似乎是从非常糟糕的 Unix 示例中复制而来的,而不是几乎在其他任何地方都有优先级队列而不是雷鸣般的羊群。当监视器和 Objective Pascal 的作者 Per Brinch Hansen看到 Java 时,他评论说“显然我的工作是徒劳的”。

于 2013-11-10T11:25:04.683 回答
0

在同步方法/块或对它们的访问之间没有“优先级”之类的东西。如果其他线程已经持有对象的监视器(即,如果另一个同步方法或synchronized (this) {}块正在进行中并且没有通过调用 放弃监视器this.wait()),所有其他线程将不得不等待直到它完成。

如果使用正确,包中的某些类java.util.concurrent可能会对您有所帮助,例如优先级队列。关于如何正确使用它们的完整指导可能超出了这个问题的范围——你应该先阅读一个体面的教程

于 2013-11-10T11:30:25.673 回答
0

在 的情况下synchronized,如果多个线程正在等待锁,则访问是随机的。但是,如果您需要先到先得:那么您可能可以使用`ReentrantLock(fairness)。这就是api所说的:

此类的构造函数接受一个可选的公平参数。当设置为 true 时,在争用情况下,锁有利于授予对等待时间最长的线程的访问权限。

否则,如果您希望根据其他因素授予访问权限,那么我想构建一个应该不复杂。lock如果其他线程正在执行,则有一个类,当调用被阻塞时。调用unlock时,它将根据您希望的任何算法解除阻塞线程。

于 2013-11-10T11:34:58.470 回答