2008-10-08 22 views
6

Tôi quen thuộc với Java, C và C++, trong đó có nhiều cách để kiểm soát chỉ một luồng truy cập tài nguyên tại bất kỳ thời điểm nào. Bây giờ tôi đang tìm kiếm một cái gì đó tương tự nhưng trong PHP 5.x.Truy cập tập tin được đồng bộ hóa 5.x PHP (không có cơ sở dữ liệu)

Xây dựng vấn đề của tôi với một ví dụ:

Tôi có một ASCII-file mà chỉ lưu trữ một số lượng, giá trị của một bộ đếm tải trang. Khi triển khai ứng dụng, tệp sẽ đơn giản giữ 0. Đối với mỗi truy cập, giá trị sẽ được tăng thêm một. Mục đích là để theo dõi tải trang.

Sự cố xảy ra khi nhiều người dùng đồng thời truy cập trang chứa bộ đếm. Khi luồng A đã đọc giá trị hiện tại, giả sử nó là 11, một chuỗi khác mà chúng ta gọi là B đọc giá trị, vẫn còn 11. Sau đó, chuỗi A đầu tiên tăng giá trị đọc và ghi 12 trong tệp và đóng nó. Sau đó, chuỗi thứ hai B, tăng giá trị đọc, là 11, nhận được 12 và ghi nó vào tệp. Giá trị 12 được lưu trữ trong tệp, khi nó thực sự phải là 13.

Trong ngôn ngữ lập trình khác, tôi đã giải quyết điều này bằng cách sử dụng mutex. Tôi hiểu có mutexes, bộ nhớ chia sẻ và funcionality khác như là một phần của mô-đun. Nhưng tôi muốn một giải pháp hoạt động trên "hầu hết các máy chủ" trên mạng. Nền tảng độc lập. Được cài đặt trên hầu hết các máy chủ web giá rẻ. Có một giải pháp tốt cho vấn đề này? Và nếu không có, bạn sẽ sử dụng cách nào nếu sử dụng cơ sở dữ liệu không phải là tùy chọn?

Trả lời

7

Bạn có thể thử biến php của bầy (http://www.php.net/flock)

Tôi sẽ hình dung một cái gì đó tương tự như (điều này giả định rằng các tập tin /tmp/counter.txt đã tồn tại và có một bộ đếm trong file):

<?php 

$fp = fopen("/tmp/counter.txt", "r+"); 

echo "Attempt to lock\n"; 
if (flock($fp, LOCK_EX)) { 
    echo "Locked\n"; 
    // Read current value of the counter and increment 
    $cntr = fread($fp, 80); 
    $cntr = intval($cntr) + 1; 

    // Pause to prove that race condition doesn't exist 
    sleep(5); 

    // Write new value to the file 
    ftruncate($fp, 0); 
    fseek($fp, 0, SEEK_SET); 
    fwrite($fp, $cntr); 
    flock($fp, LOCK_UN); // release the lock 
    fclose($fp); 
} 

?> 
+0

Câu trả lời thông tin với giải pháp cho vấn đề ví dụ, cảm ơn bạn! Tôi nghĩ rằng flock gọi ($ fp, LOCK_UN) là tốt đẹp mặc dù fclose ($ fp) cũng phát hành khóa. Tuy nhiên, tôi có một câu hỏi, tại sao bạn chắp thêm dấu cách trước dòng mới trong fwrite ($ fp, $ cntr. "\ N")? –

+0

Rất tiếc, đó là phần còn lại của sự phát triển ban đầu của tôi. Tôi sẽ chỉ sử dụng fseek mà không có ftruncate. Thêm không gian, đảm bảo rằng nó sẽ xóa bất kỳ ký tự nào khác trên dòng (quan trọng hơn cho việc giảm dần.) Chỉnh sửa ở trên, vì nó không cần thiết nữa. – terson

3

Hàm băm của PHP() là tuyến đi. Tuy nhiên, bạn phải đảm bảo rằng tất cả các truy cập vào tệp được bảo vệ bằng lệnh gọi đến flock() trước tiên. PHP sẽ không kiểm tra xem tệp có bị khóa hay không trừ khi bạn thực hiện cuộc gọi một cách rõ ràng.

Khái niệm này hầu như giống hệt với mutexes (bảo vệ tài nguyên được chia sẻ, et al), nhưng điều quan trọng là đủ để nhấn mạnh đặc biệt.

Các vấn đề liên quan