A brief analysis of concurrency control in Java multiprocess programming

  • 2020-04-01 04:21:57
  • OfStack

Interprocess communication is nothing more than reading and writing files, socket communication, or using Shared memory.
Java can't manage memory, and it does so by creating image files.
  Shared embedded implementations in Java
The MappedByteBuffer class provided in jdk1.4 provides a better way to implement Shared memory. The buffer is actually a memory image of a disk file. The changes will be kept in sync, that is, the changes in the memory data will be immediately reflected in the disk file, which will effectively guarantee the implementation of Shared memory.

The connection between Shared memory and disk files is a FileChannel class: FileChannel. This class was added to the JDK to unify access to external devices (files, network interfaces, etc.) and to enhance the security of multiple threads accessing the same file. For example, read and write operations are unified into read and write. This is just used to create Shared memory. It creates a channel between Shared memory and disk files.

To open a file and create a file channel, you can use the method getChannel in the RandomAccessFile class. This method returns a file channel directly. Since the corresponding file is set as a random access file, the file channel can be used for both read and write operations, and on the other hand, the contents of the image file will not be broken by using it (if you open an image file directly with a FileOutputStream, the size of the file will be set to 0, and of course all the data will be lost). Here, FileOutputStream and FileInputStream are not ideal for Shared memory because it is much harder for both classes to read and write freely at the same time.

The following code implements the above functionality and ACTS like the mmap function on UNIX systems.


//Gets a read-only random access file object
RandomAccessFile RAFile = new RandomAccessFile(filename,"r");
//Get the appropriate file channel
FileChannel fc = RAFile.getChannel();
//Gets the actual size of the file for image into Shared memory
int size = (int)fc.size();
//Gets the Shared memory buffer, which is read-only
MappedByteBuffer mapBuf = fc.map(FileChannel.MAP_RO,0,size);
//Gets a read-write random access file object
RAFile = new RandomAccessFile(filename,"rw");
//Get the appropriate file channel
fc = RAFile.getChannel();
//Gets the actual size of the file for image into Shared memory
size = (int)fc.size();
//Gets the Shared memory buffer, which can be read and written
mapBuf = fc.map(FileChannel.MAP_RW,0,size);
//Gets header message: access permissions
mode = mapBuf.getInt();

If multiple applications image Shared memory with the same file name, it means that the applications share the same memory data. These applications have equal access to files, and the refresh of data by one application is updated to multiple applications.
To prevent multiple applications from writing to Shared memory at the same time, a write flag can be added to the header information of the Shared memory. The header of the Shared memory has at least:


int Length ;  //Length of Shared memory.
int mode; //The current access mode of the Shared memory.

 
The header information of the Shared memory is the private information of the class. When multiple applications can perform write operations on the same Shared memory, the following method should be called to start and end write operations:


public boolean StartWrite()
{
  if(mode == 0) { //Flag 0 indicates writable
   mode = 1; //Setting the flag to 1 means that other applications cannot write to the Shared memory
   mapBuf.flip(); 
   mapBuf.putInt(mode); //Write header information such as Shared memory
   return true;
 }
 else {
  return false; //Indicates that an application is already writing to the Shared memory. This application cannot write to the Shared memory
 }
}
public boolean StopWrite()
{
 mode = 0; //Free write permission
 mapBuf.flip(); 
 mapBuf.putInt(mode); //Writes the Shared memory header information
 return true;
}

The class file provided here, mmap.java, encapsulates the basic interface to Shared memory, and readers can use this class to extend to their own comprehensive classes.
 
If the application that is writing is aborted, the Shared memory of the image file will no longer be able to write. In order for the write ban flag to be automatically eliminated after an application aborts abnormally, the running application must be made aware of the application exiting. In multithreaded applications, you can achieve this by using the synchronization method, but in multithreaded applications, synchronization does not work. There are a number of techniques that methods can employ, but this is just a description of one possible implementation: file locking. Written application in Shared memory access to a Shared memory write access, in addition to write permissions sign of judge the header information, to determine whether a temporary lock files can get, if you can get, even if the head information write permissions of the flag is 1 (above), also can start to write permissions, it has shown that write permissions for the application of already abnormal exit, the code is as follows:


//Open a temporary file and note the same Shared memory. The file name should be the same.
RandomAccessFile fis = new RandomAccessFile("shm.lock","rw");
//Get file channel
FileChannel lockfc = fis.getChannel();
//Gets an exclusive lock on the file, this method does not cause a blockage, and returns immediately
FileLock flock = lockfc.tryLock();
//If it is empty, an application has already occupied the lock
if(flock == null) {
...//A write operation cannot be performed
}else {
...//You can perform write operations
}

The lock is automatically released after the exception exits, which is exactly what is needed.


Related articles: