📅  最后修改于: 2023-12-03 15:26:05.140000             🧑  作者: Mango
UGC NET CS 2018 年 7 月 – II 的问题 64 是一道关于程序语言的问题,要求考生解释以下两种程序语言的区别:传统的基于共享变量并发编程(conventional concurrent programming based on shared variables)和使用消息传递通信(communication via message passing)的并发编程。
作为一个程序员,在开发过程中需要不断思考并发编程的问题。并发编程是指在一个程序中同时执行多个流程,这些流程之间需要相互配合和通讯,同时也需要保证系统的正确性和性能。
在传统的并发编程模型中,线程之间是基于共享变量通讯的,这意味着多个线程会使用同一个变量来进行操作。在这种模型中,需要开发人员自己手动管理锁和同步来保证正确性和性能。
而使用消息传递通信的并发编程模型则是将通讯的逻辑从共享数据中分离出来。程序中所有的通讯消息都通过消息传递方式进行传递。这种模型可以避免线程之间因争用共享变量而导致的死锁和性能问题,同时也使得程序更加易于维护和调试。
以下是基于共享变量的并发编程模型的代码片段:
public class Counter {
private int count = 0;
public void increment() {
count = count + 1;
}
public int getCount() {
return count;
}
}
public class CounterThread extends Thread {
private Counter counter;
public CounterThread(Counter counter) {
this.counter = counter;
}
public void run() {
for (int i = 0; i < 10; i++) {
counter.increment();
System.out.println("Count: " + counter.getCount() + " Thread: " + Thread.currentThread().getName());
}
}
}
public class Main {
public static void main(String[] args) {
Counter counter = new Counter();
Thread thread1 = new CounterThread(counter);
Thread thread2 = new CounterThread(counter);
thread1.start();
thread2.start();
}
}
以上代码中,Counter 类用于保存计数器的值,并提供了增加计数器值和获取计数器值的方法。CounterThread 类继承自 Thread 类,用于增加 Counter 的计数器值,使用同一个 Counter 实例,从而形成并发控制。在 Main 类中启动两个 CounterThread 线程,来模拟多线程下的并发访问。
以下是使用消息传递通信的并发编程模型的代码片段:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private ServerSocket serverSocket;
public Server(int port) throws IOException {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run() {
while (true) {
try {
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
ObjectInputStream inputStream = new ObjectInputStream(server.getInputStream());
String message = (String) inputStream.readObject();
System.out.println(message);
ObjectOutputStream outputStream = new ObjectOutputStream(server.getOutputStream());
outputStream.writeObject("Hello from " + InetAddress.getLocalHost().getHostName());
server.close();
} catch (IOException e) {
e.printStackTrace();
break;
} catch (ClassNotFoundException e) {
e.printStackTrace();
break;
}
}
}
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
try {
Thread t = new Server(port);
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class Client {
private Socket client;
private ObjectOutputStream outputStream;
private ObjectInputStream inputStream;
public Client(String host, int port) {
try {
client = new Socket(host, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
outputStream = new ObjectOutputStream(client.getOutputStream());
inputStream = new ObjectInputStream(client.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
try {
outputStream.writeObject("Hello from " + client.getLocalSocketAddress());
String response = (String) inputStream.readObject();
System.out.println(response);
client.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
String server = args[0];
int port = Integer.parseInt(args[1]);
Client client = new Client(server, port);
client.run();
}
}
以上代码中,Server 类作为服务端监听指定端口的连接请求,并将收到的消息原封不动地返回回去。Client 类作为客户端向指定服务器发送消息,并等待接收响应消息。在这个模型中,服务端和客户端之间不会共享内存,而是在消息传递的基础上进行通讯,这样可以避免线程之间因争用共享变量而导致的死锁和竞争问题。