gpt4 book ai didi

java - 如何在多线程Java应用程序中实现同步

转载 作者:行者123 更新时间:2023-12-02 13:19:58 26 4
gpt4 key购买 nike

我使用 Java 设计了一个服务器客户端应用程序,并且我已经连接到多个用户的服务器。服务器提供了一些功能,例如:

  • 下载文件
  • 创建文件
  • 写入/附加文件等
<小时/>

我发现当两个或多个用户发送相同请求时需要同步的一些问题。

例如:当用户想要同时下载同一个文件时,如何使用同步块(synchronized block)或任何其他方法来同步此操作?

 //main (connecting 2 users in the server)
ServerSocket server= new ServerSocket(8080, 50);
MyThread client1=new MyThread(server);
MyThread client2=new MyThread(server);
client1.start();
client2.start();
<小时/>

这是我想要同步的方法:

//outstream = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));//output to client
//instream = new BufferedReader(new InputStreamReader(sock.getInputStream()));//input from client

public void downloadFile(File file,String name) throws FileNotFoundException, IOException {
synchronized(this)
{

if (file.exists()) {
BufferedReader readfile = new BufferedReader(new FileReader(name + ".txt"));


String newpath = "../Socket/" + name + ".txt";

BufferedWriter socketfile = new BufferedWriter(new FileWriter(newpath));
String line;

while ((line = readfile.readLine()) != null) {
outstream.write(line + "\n");
outstream.flush();
socketfile.write(line);

}
outstream.write("EOF\n");
outstream.flush();
socketfile.close();
outstream.write("Downloaded\n");
outstream.flush();
} else {
outstream.write("FAIL\n");
}
outstream.flush();

}
}
<小时/>

Note: This method is in a class that extends Thread and is being used when i want to "download" the file in the overriden method Run()

<小时/>

这个例子是否让我确信,当 2 个用户想要下载同一个文件时,其中一个用户必须等待?另一个人会得到它吗?感谢您的宝贵时间!

最佳答案

并发锁定用于为某些代码段提供互斥。对于锁定,您可以使用同步锁和非结构化锁,例如 ReentrantLock 等。

任何锁的主要目标都是为放置在其中的代码片段提供互斥,这意味着该片段一次只能由一个线程执行。锁内部的部分称为临界区。

要实现正确的锁定,仅仅将关键代码放置在那里是不够的。此外,您还必须确保仅在关键部分内对变量进行修改。因为如果您锁定了某些代码,但对内部变量的引用也传递给了某个并发执行线程,而没有任何锁定,那么在这种情况下锁定将不会拯救您,并且您将遇到数据竞争。锁仅保护关键部分的执行,并且仅保证放置在关键部分中的代码一次只能由一个线程执行。

//outstream = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));//output to client //instream = new BufferedReader(new InputStreamReader(sock.getInputStream()));//input from client

public void downloadFile(File file,String name) throws FileNotFoundException, IOException { synchronized(this) {

这个方法的所有者是谁?客户?如果是的话那就行不通了。您应该锁定同一个对象。它应该与所有需要锁定的线程共享。但在您的情况下,每个客户端都有自己的锁,而其他线程对其他线程的锁一无所知。您可以锁定 Client.class。这会起作用。

synchronize(this) vs synchronize(MyClass.class)

完成此操作后,您将获得适当的锁定来读取(下载)文件。但是写呢?想象一下在读取过程中其他线程想要修改该文件的情况。但你的锁只用于读取。您正在读取文件的开头,而另一个线程正在修改文件的结尾。因此,写入线程将成功,并且逻辑上您将得到一个损坏的文件,其中一个文件的请求和另一个文件的结尾。当然,文件系统和标准 java 库会尝试处理这种情况(通过在读取\写入中使用锁、锁定文件偏移量等),但通常这是一种可能的情况。因此,您还需要相同的写入锁。并且读写方法应该共享并使用相同的锁。

我们遇到了这样一种情况:我们的行为正确,但绩效却很低。这是我们的权衡。但我们可以做得更好。现在,我们对每种写入和读取方法使用相同的锁,这意味着我们一次只能读取或写入一个文件。但这是不正确的,因为我们可以修改或读取不同的文件而不会出现任何可能的损坏。因此,更好的方法是将锁与文件关联,而不是与整个方法关联。 nio 来帮助你。

How can I lock a file using java (if possible)

https://docs.oracle.com/javase/7/docs/api/java/nio/channels/FileLock.html

实际上,如果偏移量不同,您可以同时读取文件。由于明显的物理原因,您无法同时读取文件的同一部分。但是并发读取和处理偏移量似乎是一个巨大的开销 fmpv,我不确定您是否需要它。无论如何,这里有一些信息:Concurrent reading of a File (java preferred)

关于java - 如何在多线程Java应用程序中实现同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43607275/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com