java和c 互斥文件锁问题

来源:互联网 发布:预约学车软件 编辑:程序博客网 时间:2024/06/05 12:46

  最近调项目需要java和c访问同一个文件,涉及到文件锁问题。最开始java能识别java加的文件锁,c能识别c加的锁。但c怎么也识别不了java锁,java也识别不了c的。

通过各种查找终于找到了问题的解决方案,在一个外国网站上发现了这个提示:

Try this:
(1) Write a small java program that locks a file and sleeps (or otherwise stops executing).
(2) cat /proc/locks
(3) You'll see lines like the following:
POSIX ADVISORY READ178408:01:273840701073742826107374233525:
FLOCK ADVISORY WRITE81500:0f:97720 EOF
Identify your process ID from column 5. If column 2 is FLOCK then flock is being used. If it is POSIX then column 2 will be POSIX, indicating fcntl (or lockf which is build on top of fcntl) is being used.
If java has to choose one or the other then POSIX would be the sensible choice as it supports record locking.
按照此方法发现c用的是FLOCK,java 用的是POSIX 找到问题所在了。c换POSIX 锁。

附加可行的例子代码(注意不同的系统上锁的方式是不一样的, 请在你的linux里头用上面的 cat /proc/locks查看你加锁的方式。

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Date;
import java.io.*;


public class FileLockTest {


    public static void main(String[] args){
        FileChannel channel = null;
        FileLock lock = null;
        File file=new File("file_lock.test"); 
        try {
            //1. 对于一个只读文件通过任意方式加锁时会报NonWritableChannelException异常
            //2. 无参lock()默认为独占锁,不会报NonReadableChannelException异常,因为独占就是为了写
            //3. 有参lock()为共享锁,所谓的共享也只能读共享,写是独占的,共享锁控制的代码只能是读操作,当有写冲突时会报NonWritableChannelException异常
            //channel = new FileOutputStream("file_lock.test",true).getChannel();
            RandomAccessFile raf = new RandomAccessFile(file,"rw");

            //在文件末尾追加内容的处理
            channel = raf.getChannel();

while(true){    
                //try {  
                    lock = channel.lock();  
System.out.println("有其他线程正在操作该文件,当前线程休眠1000毫秒");
                    break;  
                //}
//catch (Exception e) {  
                //     System.out.println("有其他线程正在操作该文件,当前线程休眠1000毫秒");   
                //     Thread.sleep(2000);    
                //} 
            }
            //获得锁方法一:lock(),阻塞的方法,当文件锁不可用时,当前进程会被挂起
            //lock = channel.lock();//无参lock()为独占锁
            //lock = channel.lock(0L, Long.MAX_VALUE, true);//有参lock()为共享锁,有写操作会报异常


            //获得锁方法二:trylock(),非阻塞的方法,当文件锁不可用时,tryLock()会得到null值
            //do {
            //  lock = channel.tryLock();
            //} while (null == lock);


            //互斥操作
            //ByteBuffer sendBuffer=ByteBuffer.wrap((new Date()+" 写入\n").getBytes());
            //channel.write(sendBuffer);
            Thread.sleep(30000);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock != null) {
                try {
                    lock.release();
                    lock = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }


            if (channel != null) {
                try {
                    channel.close();
                    channel = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}



/* 
 * write_lock.c 
 * 
 *  Created on: 2012-7-17 
 *      Author: liwei.cai 
 */  
#include <unistd.h>  
#include <sys/file.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <stdio.h>  
#include <stdlib.h>


int lock_set(int fd, int type);  
  
int main()  
{  
    int fd;  
  
    //首先打开文件  
    fd = open("./file_lock.test", O_RDWR|O_CREAT, 0644);  
    if (fd < 0)  
    {  
        printf("Open file error!\n");  
        exit(1);  
    }  
    //给文件上写入锁  
    lock_set(fd, F_WRLCK);  
    getchar();
    //给文件解锁  
    lock_set(fd, F_UNLCK);  
    getchar();  
    close(fd);  
    exit(0);  





/* 
 * lock_set.c 
 * 
 *  Created on: 2012-7-17 
 *      Author: liwei.cai 
 */  
int lock_set(int fd, int type)  
{  
    struct flock old_lock, lock;  
    lock.l_whence = SEEK_SET;  
    lock.l_start = 0;  
    lock.l_len = 0;  
    lock.l_type = type;  
    lock.l_pid -1;  
  
    //判断文件是否上锁  
    fcntl(fd, F_GETLK, &lock);  
    if (lock.l_type != F_UNLCK)  
    {  
        //判断文件不能上锁的原因  
        if (lock.l_type == F_RDLCK) //该文件已有读取锁  
        {  
            printf("Read lock already set by %d .\n", lock.l_pid);  
        }  
        else if(lock.l_type == F_WRLCK) //该文件已有写入锁  
        {  
            printf("Write lock already set by %d .\n", lock.l_pid);  
        }  
    }  
    //l_type 可能已被F_FETLK修改过  
    lock.l_type = type;  
  
    //根据不同的type值进行阻塞式上锁或解锁  
    if((fcntl(fd, F_SETLKW, &lock)) < 0)  
    {  
        printf("Lock failed:type = %d\n", lock.l_type);  
        return 1;  
    }  
  
    switch(lock.l_type)  
    {  
    case F_RDLCK:  
        {  
            printf("Read lock set by %d \n", getpid());  
        }  
        break;  
    case F_WRLCK:  
        {  
            printf("Write lock set by %d \n", getpid());  
        }  
        break;  
    case F_UNLCK:  
        {  
            printf("Release lock by %d \n", getpid());  
            return 1;  
        }  
        break;  
    default:  
        break;  
    }  
    return 0;  
}  


引用网址 :

http://blog.csdn.net/zy531/article/details/51735718

http://blog.csdn.net/cailiwei712/article/details/7754723

https://stackoverflow.com/questions/23562369/is-a-java-filelock-a-posix-advisory-fcntl-lock