diff --git a/Library/Homebrew/cleanup.rb b/Library/Homebrew/cleanup.rb
index 53f3ee3a2cb729c49ae108dcc665340bba737cfd..432efa2a382f060867c9544b5388c96bee4b1cfc 100644
--- a/Library/Homebrew/cleanup.rb
+++ b/Library/Homebrew/cleanup.rb
@@ -152,13 +152,13 @@ module Homebrew
 
     def clean!
       if args.empty?
-        cleanup_lockfiles
         Formula.installed.sort_by(&:name).each do |formula|
           cleanup_formula(formula)
         end
         cleanup_cache
         cleanup_logs
         cleanup_portable_ruby
+        cleanup_lockfiles
         return if dry_run?
 
         cleanup_old_cache_db
@@ -221,14 +221,27 @@ module Homebrew
       return if dry_run?
       return unless (cache/"downloads").directory?
 
-      # We can't use `.reject(&:incomplete?) here due to the refinement scope.
-      downloads = (cache/"downloads").children.reject { |path| path.incomplete? } # rubocop:disable Style/SymbolProc
+      downloads = (cache/"downloads").children
+
       referenced_downloads = [cache, cache/"Cask"].select(&:directory?)
                                                   .flat_map(&:children)
                                                   .select(&:symlink?)
                                                   .map(&:resolved_path)
 
-      (downloads - referenced_downloads).each(&:unlink)
+      (downloads - referenced_downloads).each do |download|
+        if download.incomplete?
+          begin
+            LockFile.new(download.basename).with_lock do
+              download.unlink
+            end
+          rescue OperationInProgressError
+            # Skip incomplete downloads which are still in progress.
+            next
+          end
+        else
+          download.unlink
+        end
+      end
     end
 
     def cleanup_cache(entries = nil)
diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb
index 89a79c6e0b193dfcd3df1e3c1c3ba40784e18819..2c8cff34c5b6f414ab22235f113353863f23d616 100644
--- a/Library/Homebrew/download_strategy.rb
+++ b/Library/Homebrew/download_strategy.rb
@@ -277,6 +277,9 @@ class CurlDownloadStrategy < AbstractFileDownloadStrategy
   end
 
   def fetch
+    download_lock = LockFile.new(temporary_path.basename)
+    download_lock.lock
+
     urls = [url, *mirrors]
 
     begin
@@ -308,6 +311,8 @@ class CurlDownloadStrategy < AbstractFileDownloadStrategy
       puts "Trying a mirror..."
       retry
     end
+  ensure
+    download_lock.unlock
   end
 
   def clear_cache